diff --git a/.github/actions/deploy-service/action.yaml b/.github/actions/deploy-service/action.yaml index 922d93eefd..f21c4e915c 100644 --- a/.github/actions/deploy-service/action.yaml +++ b/.github/actions/deploy-service/action.yaml @@ -14,6 +14,16 @@ inputs: description: To which cloud cluster to deploy required: true + prioritized: + description: Is the service listening on prioritized queues? + required: false + default: 'false' + + cloud_env: + description: Which cloud environment are we deploying to? + required: false + default: 'default' + runs: using: composite steps: @@ -25,10 +35,38 @@ runs: AWS_SECRET_ACCESS_KEY: ${{ env.AWS_SECRET_ACCESS_KEY }} AWS_REGION: ${{ env.AWS_REGION }} - - name: Deploy image + - name: Deploy image (non prioritized) + if: inputs.prioritized == 'false' shell: bash run: kubectl set image deployments/${{ inputs.service }}-dpl ${{ inputs.service }}=${{ inputs.image }} + - name: Deploy image (prioritized - production) + if: inputs.prioritized == 'true' && inputs.cloud_env == 'prod' + shell: bash + run: | + kubectl set image deployments/${{ inputs.service }}-system-dpl ${{ inputs.service }}-system=${{ inputs.image }} + kubectl set image deployments/${{ inputs.service }}-normal-dpl ${{ inputs.service }}-normal=${{ inputs.image }} + kubectl set image deployments/${{ inputs.service }}-high-dpl ${{ inputs.service }}-high=${{ inputs.image }} + kubectl set image deployments/${{ inputs.service }}-urgent-dpl ${{ inputs.service }}-urgent=${{ inputs.image }} + + - name: Deploy image (prioritized - lfx production) + if: inputs.prioritized == 'true' && inputs.cloud_env == 'lfx_prod' + shell: bash + run: | + kubectl set image deployments/${{ inputs.service }}-system-dpl ${{ inputs.service }}-system=${{ inputs.image }} + kubectl set image deployments/${{ inputs.service }}-normal-dpl ${{ inputs.service }}-normal=${{ inputs.image }} + kubectl set image deployments/${{ inputs.service }}-high-dpl ${{ inputs.service }}-high=${{ inputs.image }} + + - name: Deploy image (prioritized - staging) + if: inputs.prioritized == 'true' && inputs.cloud_env == 'staging' + shell: bash + run: kubectl set image deployments/${{ inputs.service }}-normal-dpl ${{ inputs.service }}-normal=${{ inputs.image }} + + - name: Deploy image (prioritized - lfx staging) + if: inputs.prioritized == 'true' && inputs.cloud_env == 'lfx_staging' + shell: bash + run: kubectl set image deployments/${{ inputs.service }}-normal-dpl ${{ inputs.service }}-normal=${{ inputs.image }} + - uses: ./.github/actions/slack-notify with: message: 'Service *${{ inputs.service }}* was just deployed using docker image `${{ inputs.image }}`' diff --git a/.github/actions/node/.eslintrc.cjs b/.github/actions/node/.eslintrc.cjs new file mode 100644 index 0000000000..25ba4e0d66 --- /dev/null +++ b/.github/actions/node/.eslintrc.cjs @@ -0,0 +1,21 @@ +module.exports = { + parser: '@typescript-eslint/parser', + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:prettier/recommended', + ], + plugins: ['@typescript-eslint', 'prettier'], + parserOptions: { + ecmaVersion: 2022, + sourceType: 'module', + }, + env: { + es6: true, + node: true, + }, + rules: { + 'prettier/prettier': 'error', + '@typescript-eslint/explicit-module-boundary-types': 'off', + }, +} diff --git a/.github/actions/node/.gitignore b/.github/actions/node/.gitignore new file mode 100644 index 0000000000..dc8cdbdf62 --- /dev/null +++ b/.github/actions/node/.gitignore @@ -0,0 +1,3 @@ +node_modules/ +dist/ +out/ \ No newline at end of file diff --git a/.github/actions/node/.prettierignore b/.github/actions/node/.prettierignore new file mode 100644 index 0000000000..2b24877309 --- /dev/null +++ b/.github/actions/node/.prettierignore @@ -0,0 +1,3 @@ +dist/ +.eslintrc.cjs +.prettierrc.cjs diff --git a/.github/actions/node/.prettierrc.cjs b/.github/actions/node/.prettierrc.cjs new file mode 100644 index 0000000000..a8ca459839 --- /dev/null +++ b/.github/actions/node/.prettierrc.cjs @@ -0,0 +1,7 @@ +module.exports = { + singleQuote: true, + arrowParens: 'always', + printWidth: 100, + trailingComma: 'all', + semi: false, +} diff --git a/.github/actions/node/builder/action.yaml b/.github/actions/node/builder/action.yaml new file mode 100644 index 0000000000..a2178325a4 --- /dev/null +++ b/.github/actions/node/builder/action.yaml @@ -0,0 +1,20 @@ +name: Deployer +description: Custom Deployer Action + +inputs: + services: + description: Services to deploy + required: true + tag: + description: Tag for images + required: false + default: ${{ github.sha }} + steps: + description: Steps to run + required: false + default: build push deploy + +runs: + using: node16 + main: index.js + post: index.js diff --git a/.github/actions/node/builder/index.js b/.github/actions/node/builder/index.js new file mode 100644 index 0000000000..ec29f62447 --- /dev/null +++ b/.github/actions/node/builder/index.js @@ -0,0 +1,28559 @@ +/******/ (() => { // webpackBootstrap +/******/ var __webpack_modules__ = ({ + +/***/ 8911: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.issue = exports.issueCommand = void 0; +const os = __importStar(__nccwpck_require__(2037)); +const utils_1 = __nccwpck_require__(6657); +/** + * Commands + * + * Command Format: + * ::name key=value,key=value::message + * + * Examples: + * ::warning::This is the message + * ::set-env name=MY_VAR::some value + */ +function issueCommand(command, properties, message) { + const cmd = new Command(command, properties, message); + process.stdout.write(cmd.toString() + os.EOL); +} +exports.issueCommand = issueCommand; +function issue(name, message = '') { + issueCommand(name, {}, message); +} +exports.issue = issue; +const CMD_STRING = '::'; +class Command { + constructor(command, properties, message) { + if (!command) { + command = 'missing.command'; + } + this.command = command; + this.properties = properties; + this.message = message; + } + toString() { + let cmdStr = CMD_STRING + this.command; + if (this.properties && Object.keys(this.properties).length > 0) { + cmdStr += ' '; + let first = true; + for (const key in this.properties) { + if (this.properties.hasOwnProperty(key)) { + const val = this.properties[key]; + if (val) { + if (first) { + first = false; + } + else { + cmdStr += ','; + } + cmdStr += `${key}=${escapeProperty(val)}`; + } + } + } + } + cmdStr += `${CMD_STRING}${escapeData(this.message)}`; + return cmdStr; + } +} +function escapeData(s) { + return utils_1.toCommandValue(s) + .replace(/%/g, '%25') + .replace(/\r/g, '%0D') + .replace(/\n/g, '%0A'); +} +function escapeProperty(s) { + return utils_1.toCommandValue(s) + .replace(/%/g, '%25') + .replace(/\r/g, '%0D') + .replace(/\n/g, '%0A') + .replace(/:/g, '%3A') + .replace(/,/g, '%2C'); +} +//# sourceMappingURL=command.js.map + +/***/ }), + +/***/ 3949: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getIDToken = exports.getState = exports.saveState = exports.group = exports.endGroup = exports.startGroup = exports.info = exports.notice = exports.warning = exports.error = exports.debug = exports.isDebug = exports.setFailed = exports.setCommandEcho = exports.setOutput = exports.getBooleanInput = exports.getMultilineInput = exports.getInput = exports.addPath = exports.setSecret = exports.exportVariable = exports.ExitCode = void 0; +const command_1 = __nccwpck_require__(8911); +const file_command_1 = __nccwpck_require__(807); +const utils_1 = __nccwpck_require__(6657); +const os = __importStar(__nccwpck_require__(2037)); +const path = __importStar(__nccwpck_require__(1017)); +const oidc_utils_1 = __nccwpck_require__(7101); +/** + * The code to exit an action + */ +var ExitCode; +(function (ExitCode) { + /** + * A code indicating that the action was successful + */ + ExitCode[ExitCode["Success"] = 0] = "Success"; + /** + * A code indicating that the action was a failure + */ + ExitCode[ExitCode["Failure"] = 1] = "Failure"; +})(ExitCode = exports.ExitCode || (exports.ExitCode = {})); +//----------------------------------------------------------------------- +// Variables +//----------------------------------------------------------------------- +/** + * Sets env variable for this action and future actions in the job + * @param name the name of the variable to set + * @param val the value of the variable. Non-string values will be converted to a string via JSON.stringify + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function exportVariable(name, val) { + const convertedVal = utils_1.toCommandValue(val); + process.env[name] = convertedVal; + const filePath = process.env['GITHUB_ENV'] || ''; + if (filePath) { + return file_command_1.issueFileCommand('ENV', file_command_1.prepareKeyValueMessage(name, val)); + } + command_1.issueCommand('set-env', { name }, convertedVal); +} +exports.exportVariable = exportVariable; +/** + * Registers a secret which will get masked from logs + * @param secret value of the secret + */ +function setSecret(secret) { + command_1.issueCommand('add-mask', {}, secret); +} +exports.setSecret = setSecret; +/** + * Prepends inputPath to the PATH (for this action and future actions) + * @param inputPath + */ +function addPath(inputPath) { + const filePath = process.env['GITHUB_PATH'] || ''; + if (filePath) { + file_command_1.issueFileCommand('PATH', inputPath); + } + else { + command_1.issueCommand('add-path', {}, inputPath); + } + process.env['PATH'] = `${inputPath}${path.delimiter}${process.env['PATH']}`; +} +exports.addPath = addPath; +/** + * Gets the value of an input. + * Unless trimWhitespace is set to false in InputOptions, the value is also trimmed. + * Returns an empty string if the value is not defined. + * + * @param name name of the input to get + * @param options optional. See InputOptions. + * @returns string + */ +function getInput(name, options) { + const val = process.env[`INPUT_${name.replace(/ /g, '_').toUpperCase()}`] || ''; + if (options && options.required && !val) { + throw new Error(`Input required and not supplied: ${name}`); + } + if (options && options.trimWhitespace === false) { + return val; + } + return val.trim(); +} +exports.getInput = getInput; +/** + * Gets the values of an multiline input. Each value is also trimmed. + * + * @param name name of the input to get + * @param options optional. See InputOptions. + * @returns string[] + * + */ +function getMultilineInput(name, options) { + const inputs = getInput(name, options) + .split('\n') + .filter(x => x !== ''); + if (options && options.trimWhitespace === false) { + return inputs; + } + return inputs.map(input => input.trim()); +} +exports.getMultilineInput = getMultilineInput; +/** + * Gets the input value of the boolean type in the YAML 1.2 "core schema" specification. + * Support boolean input list: `true | True | TRUE | false | False | FALSE` . + * The return value is also in boolean type. + * ref: https://yaml.org/spec/1.2/spec.html#id2804923 + * + * @param name name of the input to get + * @param options optional. See InputOptions. + * @returns boolean + */ +function getBooleanInput(name, options) { + const trueValue = ['true', 'True', 'TRUE']; + const falseValue = ['false', 'False', 'FALSE']; + const val = getInput(name, options); + if (trueValue.includes(val)) + return true; + if (falseValue.includes(val)) + return false; + throw new TypeError(`Input does not meet YAML 1.2 "Core Schema" specification: ${name}\n` + + `Support boolean input list: \`true | True | TRUE | false | False | FALSE\``); +} +exports.getBooleanInput = getBooleanInput; +/** + * Sets the value of an output. + * + * @param name name of the output to set + * @param value value to store. Non-string values will be converted to a string via JSON.stringify + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function setOutput(name, value) { + const filePath = process.env['GITHUB_OUTPUT'] || ''; + if (filePath) { + return file_command_1.issueFileCommand('OUTPUT', file_command_1.prepareKeyValueMessage(name, value)); + } + process.stdout.write(os.EOL); + command_1.issueCommand('set-output', { name }, utils_1.toCommandValue(value)); +} +exports.setOutput = setOutput; +/** + * Enables or disables the echoing of commands into stdout for the rest of the step. + * Echoing is disabled by default if ACTIONS_STEP_DEBUG is not set. + * + */ +function setCommandEcho(enabled) { + command_1.issue('echo', enabled ? 'on' : 'off'); +} +exports.setCommandEcho = setCommandEcho; +//----------------------------------------------------------------------- +// Results +//----------------------------------------------------------------------- +/** + * Sets the action status to failed. + * When the action exits it will be with an exit code of 1 + * @param message add error issue message + */ +function setFailed(message) { + process.exitCode = ExitCode.Failure; + error(message); +} +exports.setFailed = setFailed; +//----------------------------------------------------------------------- +// Logging Commands +//----------------------------------------------------------------------- +/** + * Gets whether Actions Step Debug is on or not + */ +function isDebug() { + return process.env['RUNNER_DEBUG'] === '1'; +} +exports.isDebug = isDebug; +/** + * Writes debug message to user log + * @param message debug message + */ +function debug(message) { + command_1.issueCommand('debug', {}, message); +} +exports.debug = debug; +/** + * Adds an error issue + * @param message error issue message. Errors will be converted to string via toString() + * @param properties optional properties to add to the annotation. + */ +function error(message, properties = {}) { + command_1.issueCommand('error', utils_1.toCommandProperties(properties), message instanceof Error ? message.toString() : message); +} +exports.error = error; +/** + * Adds a warning issue + * @param message warning issue message. Errors will be converted to string via toString() + * @param properties optional properties to add to the annotation. + */ +function warning(message, properties = {}) { + command_1.issueCommand('warning', utils_1.toCommandProperties(properties), message instanceof Error ? message.toString() : message); +} +exports.warning = warning; +/** + * Adds a notice issue + * @param message notice issue message. Errors will be converted to string via toString() + * @param properties optional properties to add to the annotation. + */ +function notice(message, properties = {}) { + command_1.issueCommand('notice', utils_1.toCommandProperties(properties), message instanceof Error ? message.toString() : message); +} +exports.notice = notice; +/** + * Writes info to log with console.log. + * @param message info message + */ +function info(message) { + process.stdout.write(message + os.EOL); +} +exports.info = info; +/** + * Begin an output group. + * + * Output until the next `groupEnd` will be foldable in this group + * + * @param name The name of the output group + */ +function startGroup(name) { + command_1.issue('group', name); +} +exports.startGroup = startGroup; +/** + * End an output group. + */ +function endGroup() { + command_1.issue('endgroup'); +} +exports.endGroup = endGroup; +/** + * Wrap an asynchronous function call in a group. + * + * Returns the same type as the function itself. + * + * @param name The name of the group + * @param fn The function to wrap in the group + */ +function group(name, fn) { + return __awaiter(this, void 0, void 0, function* () { + startGroup(name); + let result; + try { + result = yield fn(); + } + finally { + endGroup(); + } + return result; + }); +} +exports.group = group; +//----------------------------------------------------------------------- +// Wrapper action state +//----------------------------------------------------------------------- +/** + * Saves state for current action, the state can only be retrieved by this action's post job execution. + * + * @param name name of the state to store + * @param value value to store. Non-string values will be converted to a string via JSON.stringify + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function saveState(name, value) { + const filePath = process.env['GITHUB_STATE'] || ''; + if (filePath) { + return file_command_1.issueFileCommand('STATE', file_command_1.prepareKeyValueMessage(name, value)); + } + command_1.issueCommand('save-state', { name }, utils_1.toCommandValue(value)); +} +exports.saveState = saveState; +/** + * Gets the value of an state set by this action's main execution. + * + * @param name name of the state to get + * @returns string + */ +function getState(name) { + return process.env[`STATE_${name}`] || ''; +} +exports.getState = getState; +function getIDToken(aud) { + return __awaiter(this, void 0, void 0, function* () { + return yield oidc_utils_1.OidcClient.getIDToken(aud); + }); +} +exports.getIDToken = getIDToken; +/** + * Summary exports + */ +var summary_1 = __nccwpck_require__(3801); +Object.defineProperty(exports, "summary", ({ enumerable: true, get: function () { return summary_1.summary; } })); +/** + * @deprecated use core.summary + */ +var summary_2 = __nccwpck_require__(3801); +Object.defineProperty(exports, "markdownSummary", ({ enumerable: true, get: function () { return summary_2.markdownSummary; } })); +/** + * Path exports + */ +var path_utils_1 = __nccwpck_require__(8169); +Object.defineProperty(exports, "toPosixPath", ({ enumerable: true, get: function () { return path_utils_1.toPosixPath; } })); +Object.defineProperty(exports, "toWin32Path", ({ enumerable: true, get: function () { return path_utils_1.toWin32Path; } })); +Object.defineProperty(exports, "toPlatformPath", ({ enumerable: true, get: function () { return path_utils_1.toPlatformPath; } })); +//# sourceMappingURL=core.js.map + +/***/ }), + +/***/ 807: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// For internal use, subject to change. +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.prepareKeyValueMessage = exports.issueFileCommand = void 0; +// We use any as a valid input type +/* eslint-disable @typescript-eslint/no-explicit-any */ +const fs = __importStar(__nccwpck_require__(7147)); +const os = __importStar(__nccwpck_require__(2037)); +const uuid_1 = __nccwpck_require__(6328); +const utils_1 = __nccwpck_require__(6657); +function issueFileCommand(command, message) { + const filePath = process.env[`GITHUB_${command}`]; + if (!filePath) { + throw new Error(`Unable to find environment variable for file command ${command}`); + } + if (!fs.existsSync(filePath)) { + throw new Error(`Missing file at path: ${filePath}`); + } + fs.appendFileSync(filePath, `${utils_1.toCommandValue(message)}${os.EOL}`, { + encoding: 'utf8' + }); +} +exports.issueFileCommand = issueFileCommand; +function prepareKeyValueMessage(key, value) { + const delimiter = `ghadelimiter_${uuid_1.v4()}`; + const convertedValue = utils_1.toCommandValue(value); + // These should realistically never happen, but just in case someone finds a + // way to exploit uuid generation let's not allow keys or values that contain + // the delimiter. + if (key.includes(delimiter)) { + throw new Error(`Unexpected input: name should not contain the delimiter "${delimiter}"`); + } + if (convertedValue.includes(delimiter)) { + throw new Error(`Unexpected input: value should not contain the delimiter "${delimiter}"`); + } + return `${key}<<${delimiter}${os.EOL}${convertedValue}${os.EOL}${delimiter}`; +} +exports.prepareKeyValueMessage = prepareKeyValueMessage; +//# sourceMappingURL=file-command.js.map + +/***/ }), + +/***/ 7101: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.OidcClient = void 0; +const http_client_1 = __nccwpck_require__(5753); +const auth_1 = __nccwpck_require__(7910); +const core_1 = __nccwpck_require__(3949); +class OidcClient { + static createHttpClient(allowRetry = true, maxRetry = 10) { + const requestOptions = { + allowRetries: allowRetry, + maxRetries: maxRetry + }; + return new http_client_1.HttpClient('actions/oidc-client', [new auth_1.BearerCredentialHandler(OidcClient.getRequestToken())], requestOptions); + } + static getRequestToken() { + const token = process.env['ACTIONS_ID_TOKEN_REQUEST_TOKEN']; + if (!token) { + throw new Error('Unable to get ACTIONS_ID_TOKEN_REQUEST_TOKEN env variable'); + } + return token; + } + static getIDTokenUrl() { + const runtimeUrl = process.env['ACTIONS_ID_TOKEN_REQUEST_URL']; + if (!runtimeUrl) { + throw new Error('Unable to get ACTIONS_ID_TOKEN_REQUEST_URL env variable'); + } + return runtimeUrl; + } + static getCall(id_token_url) { + var _a; + return __awaiter(this, void 0, void 0, function* () { + const httpclient = OidcClient.createHttpClient(); + const res = yield httpclient + .getJson(id_token_url) + .catch(error => { + throw new Error(`Failed to get ID Token. \n + Error Code : ${error.statusCode}\n + Error Message: ${error.message}`); + }); + const id_token = (_a = res.result) === null || _a === void 0 ? void 0 : _a.value; + if (!id_token) { + throw new Error('Response json body do not have ID Token field'); + } + return id_token; + }); + } + static getIDToken(audience) { + return __awaiter(this, void 0, void 0, function* () { + try { + // New ID Token is requested from action service + let id_token_url = OidcClient.getIDTokenUrl(); + if (audience) { + const encodedAudience = encodeURIComponent(audience); + id_token_url = `${id_token_url}&audience=${encodedAudience}`; + } + core_1.debug(`ID token url is ${id_token_url}`); + const id_token = yield OidcClient.getCall(id_token_url); + core_1.setSecret(id_token); + return id_token; + } + catch (error) { + throw new Error(`Error message: ${error.message}`); + } + }); + } +} +exports.OidcClient = OidcClient; +//# sourceMappingURL=oidc-utils.js.map + +/***/ }), + +/***/ 8169: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.toPlatformPath = exports.toWin32Path = exports.toPosixPath = void 0; +const path = __importStar(__nccwpck_require__(1017)); +/** + * toPosixPath converts the given path to the posix form. On Windows, \\ will be + * replaced with /. + * + * @param pth. Path to transform. + * @return string Posix path. + */ +function toPosixPath(pth) { + return pth.replace(/[\\]/g, '/'); +} +exports.toPosixPath = toPosixPath; +/** + * toWin32Path converts the given path to the win32 form. On Linux, / will be + * replaced with \\. + * + * @param pth. Path to transform. + * @return string Win32 path. + */ +function toWin32Path(pth) { + return pth.replace(/[/]/g, '\\'); +} +exports.toWin32Path = toWin32Path; +/** + * toPlatformPath converts the given path to a platform-specific path. It does + * this by replacing instances of / and \ with the platform-specific path + * separator. + * + * @param pth The path to platformize. + * @return string The platform-specific path. + */ +function toPlatformPath(pth) { + return pth.replace(/[/\\]/g, path.sep); +} +exports.toPlatformPath = toPlatformPath; +//# sourceMappingURL=path-utils.js.map + +/***/ }), + +/***/ 3801: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.summary = exports.markdownSummary = exports.SUMMARY_DOCS_URL = exports.SUMMARY_ENV_VAR = void 0; +const os_1 = __nccwpck_require__(2037); +const fs_1 = __nccwpck_require__(7147); +const { access, appendFile, writeFile } = fs_1.promises; +exports.SUMMARY_ENV_VAR = 'GITHUB_STEP_SUMMARY'; +exports.SUMMARY_DOCS_URL = 'https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#adding-a-job-summary'; +class Summary { + constructor() { + this._buffer = ''; + } + /** + * Finds the summary file path from the environment, rejects if env var is not found or file does not exist + * Also checks r/w permissions. + * + * @returns step summary file path + */ + filePath() { + return __awaiter(this, void 0, void 0, function* () { + if (this._filePath) { + return this._filePath; + } + const pathFromEnv = process.env[exports.SUMMARY_ENV_VAR]; + if (!pathFromEnv) { + throw new Error(`Unable to find environment variable for $${exports.SUMMARY_ENV_VAR}. Check if your runtime environment supports job summaries.`); + } + try { + yield access(pathFromEnv, fs_1.constants.R_OK | fs_1.constants.W_OK); + } + catch (_a) { + throw new Error(`Unable to access summary file: '${pathFromEnv}'. Check if the file has correct read/write permissions.`); + } + this._filePath = pathFromEnv; + return this._filePath; + }); + } + /** + * Wraps content in an HTML tag, adding any HTML attributes + * + * @param {string} tag HTML tag to wrap + * @param {string | null} content content within the tag + * @param {[attribute: string]: string} attrs key-value list of HTML attributes to add + * + * @returns {string} content wrapped in HTML element + */ + wrap(tag, content, attrs = {}) { + const htmlAttrs = Object.entries(attrs) + .map(([key, value]) => ` ${key}="${value}"`) + .join(''); + if (!content) { + return `<${tag}${htmlAttrs}>`; + } + return `<${tag}${htmlAttrs}>${content}`; + } + /** + * Writes text in the buffer to the summary buffer file and empties buffer. Will append by default. + * + * @param {SummaryWriteOptions} [options] (optional) options for write operation + * + * @returns {Promise} summary instance + */ + write(options) { + return __awaiter(this, void 0, void 0, function* () { + const overwrite = !!(options === null || options === void 0 ? void 0 : options.overwrite); + const filePath = yield this.filePath(); + const writeFunc = overwrite ? writeFile : appendFile; + yield writeFunc(filePath, this._buffer, { encoding: 'utf8' }); + return this.emptyBuffer(); + }); + } + /** + * Clears the summary buffer and wipes the summary file + * + * @returns {Summary} summary instance + */ + clear() { + return __awaiter(this, void 0, void 0, function* () { + return this.emptyBuffer().write({ overwrite: true }); + }); + } + /** + * Returns the current summary buffer as a string + * + * @returns {string} string of summary buffer + */ + stringify() { + return this._buffer; + } + /** + * If the summary buffer is empty + * + * @returns {boolen} true if the buffer is empty + */ + isEmptyBuffer() { + return this._buffer.length === 0; + } + /** + * Resets the summary buffer without writing to summary file + * + * @returns {Summary} summary instance + */ + emptyBuffer() { + this._buffer = ''; + return this; + } + /** + * Adds raw text to the summary buffer + * + * @param {string} text content to add + * @param {boolean} [addEOL=false] (optional) append an EOL to the raw text (default: false) + * + * @returns {Summary} summary instance + */ + addRaw(text, addEOL = false) { + this._buffer += text; + return addEOL ? this.addEOL() : this; + } + /** + * Adds the operating system-specific end-of-line marker to the buffer + * + * @returns {Summary} summary instance + */ + addEOL() { + return this.addRaw(os_1.EOL); + } + /** + * Adds an HTML codeblock to the summary buffer + * + * @param {string} code content to render within fenced code block + * @param {string} lang (optional) language to syntax highlight code + * + * @returns {Summary} summary instance + */ + addCodeBlock(code, lang) { + const attrs = Object.assign({}, (lang && { lang })); + const element = this.wrap('pre', this.wrap('code', code), attrs); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML list to the summary buffer + * + * @param {string[]} items list of items to render + * @param {boolean} [ordered=false] (optional) if the rendered list should be ordered or not (default: false) + * + * @returns {Summary} summary instance + */ + addList(items, ordered = false) { + const tag = ordered ? 'ol' : 'ul'; + const listItems = items.map(item => this.wrap('li', item)).join(''); + const element = this.wrap(tag, listItems); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML table to the summary buffer + * + * @param {SummaryTableCell[]} rows table rows + * + * @returns {Summary} summary instance + */ + addTable(rows) { + const tableBody = rows + .map(row => { + const cells = row + .map(cell => { + if (typeof cell === 'string') { + return this.wrap('td', cell); + } + const { header, data, colspan, rowspan } = cell; + const tag = header ? 'th' : 'td'; + const attrs = Object.assign(Object.assign({}, (colspan && { colspan })), (rowspan && { rowspan })); + return this.wrap(tag, data, attrs); + }) + .join(''); + return this.wrap('tr', cells); + }) + .join(''); + const element = this.wrap('table', tableBody); + return this.addRaw(element).addEOL(); + } + /** + * Adds a collapsable HTML details element to the summary buffer + * + * @param {string} label text for the closed state + * @param {string} content collapsable content + * + * @returns {Summary} summary instance + */ + addDetails(label, content) { + const element = this.wrap('details', this.wrap('summary', label) + content); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML image tag to the summary buffer + * + * @param {string} src path to the image you to embed + * @param {string} alt text description of the image + * @param {SummaryImageOptions} options (optional) addition image attributes + * + * @returns {Summary} summary instance + */ + addImage(src, alt, options) { + const { width, height } = options || {}; + const attrs = Object.assign(Object.assign({}, (width && { width })), (height && { height })); + const element = this.wrap('img', null, Object.assign({ src, alt }, attrs)); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML section heading element + * + * @param {string} text heading text + * @param {number | string} [level=1] (optional) the heading level, default: 1 + * + * @returns {Summary} summary instance + */ + addHeading(text, level) { + const tag = `h${level}`; + const allowedTag = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'].includes(tag) + ? tag + : 'h1'; + const element = this.wrap(allowedTag, text); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML thematic break (
) to the summary buffer + * + * @returns {Summary} summary instance + */ + addSeparator() { + const element = this.wrap('hr', null); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML line break (
) to the summary buffer + * + * @returns {Summary} summary instance + */ + addBreak() { + const element = this.wrap('br', null); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML blockquote to the summary buffer + * + * @param {string} text quote text + * @param {string} cite (optional) citation url + * + * @returns {Summary} summary instance + */ + addQuote(text, cite) { + const attrs = Object.assign({}, (cite && { cite })); + const element = this.wrap('blockquote', text, attrs); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML anchor tag to the summary buffer + * + * @param {string} text link text/content + * @param {string} href hyperlink + * + * @returns {Summary} summary instance + */ + addLink(text, href) { + const element = this.wrap('a', text, { href }); + return this.addRaw(element).addEOL(); + } +} +const _summary = new Summary(); +/** + * @deprecated use `core.summary` + */ +exports.markdownSummary = _summary; +exports.summary = _summary; +//# sourceMappingURL=summary.js.map + +/***/ }), + +/***/ 6657: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +// We use any as a valid input type +/* eslint-disable @typescript-eslint/no-explicit-any */ +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.toCommandProperties = exports.toCommandValue = void 0; +/** + * Sanitizes an input into a string so it can be passed into issueCommand safely + * @param input input to sanitize into a string + */ +function toCommandValue(input) { + if (input === null || input === undefined) { + return ''; + } + else if (typeof input === 'string' || input instanceof String) { + return input; + } + return JSON.stringify(input); +} +exports.toCommandValue = toCommandValue; +/** + * + * @param annotationProperties + * @returns The command properties to send with the actual annotation command + * See IssueCommandProperties: https://github.com/actions/runner/blob/main/src/Runner.Worker/ActionCommandManager.cs#L646 + */ +function toCommandProperties(annotationProperties) { + if (!Object.keys(annotationProperties).length) { + return {}; + } + return { + title: annotationProperties.title, + file: annotationProperties.file, + line: annotationProperties.startLine, + endLine: annotationProperties.endLine, + col: annotationProperties.startColumn, + endColumn: annotationProperties.endColumn + }; +} +exports.toCommandProperties = toCommandProperties; +//# sourceMappingURL=utils.js.map + +/***/ }), + +/***/ 7912: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getExecOutput = exports.exec = void 0; +const string_decoder_1 = __nccwpck_require__(1576); +const tr = __importStar(__nccwpck_require__(6990)); +/** + * Exec a command. + * Output will be streamed to the live console. + * Returns promise with return code + * + * @param commandLine command to execute (can include additional args). Must be correctly escaped. + * @param args optional arguments for tool. Escaping is handled by the lib. + * @param options optional exec options. See ExecOptions + * @returns Promise exit code + */ +function exec(commandLine, args, options) { + return __awaiter(this, void 0, void 0, function* () { + const commandArgs = tr.argStringToArray(commandLine); + if (commandArgs.length === 0) { + throw new Error(`Parameter 'commandLine' cannot be null or empty.`); + } + // Path to tool to execute should be first arg + const toolPath = commandArgs[0]; + args = commandArgs.slice(1).concat(args || []); + const runner = new tr.ToolRunner(toolPath, args, options); + return runner.exec(); + }); +} +exports.exec = exec; +/** + * Exec a command and get the output. + * Output will be streamed to the live console. + * Returns promise with the exit code and collected stdout and stderr + * + * @param commandLine command to execute (can include additional args). Must be correctly escaped. + * @param args optional arguments for tool. Escaping is handled by the lib. + * @param options optional exec options. See ExecOptions + * @returns Promise exit code, stdout, and stderr + */ +function getExecOutput(commandLine, args, options) { + var _a, _b; + return __awaiter(this, void 0, void 0, function* () { + let stdout = ''; + let stderr = ''; + //Using string decoder covers the case where a mult-byte character is split + const stdoutDecoder = new string_decoder_1.StringDecoder('utf8'); + const stderrDecoder = new string_decoder_1.StringDecoder('utf8'); + const originalStdoutListener = (_a = options === null || options === void 0 ? void 0 : options.listeners) === null || _a === void 0 ? void 0 : _a.stdout; + const originalStdErrListener = (_b = options === null || options === void 0 ? void 0 : options.listeners) === null || _b === void 0 ? void 0 : _b.stderr; + const stdErrListener = (data) => { + stderr += stderrDecoder.write(data); + if (originalStdErrListener) { + originalStdErrListener(data); + } + }; + const stdOutListener = (data) => { + stdout += stdoutDecoder.write(data); + if (originalStdoutListener) { + originalStdoutListener(data); + } + }; + const listeners = Object.assign(Object.assign({}, options === null || options === void 0 ? void 0 : options.listeners), { stdout: stdOutListener, stderr: stdErrListener }); + const exitCode = yield exec(commandLine, args, Object.assign(Object.assign({}, options), { listeners })); + //flush any remaining characters + stdout += stdoutDecoder.end(); + stderr += stderrDecoder.end(); + return { + exitCode, + stdout, + stderr + }; + }); +} +exports.getExecOutput = getExecOutput; +//# sourceMappingURL=exec.js.map + +/***/ }), + +/***/ 6990: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.argStringToArray = exports.ToolRunner = void 0; +const os = __importStar(__nccwpck_require__(2037)); +const events = __importStar(__nccwpck_require__(2361)); +const child = __importStar(__nccwpck_require__(2081)); +const path = __importStar(__nccwpck_require__(1017)); +const io = __importStar(__nccwpck_require__(4721)); +const ioUtil = __importStar(__nccwpck_require__(8798)); +const timers_1 = __nccwpck_require__(9512); +/* eslint-disable @typescript-eslint/unbound-method */ +const IS_WINDOWS = process.platform === 'win32'; +/* + * Class for running command line tools. Handles quoting and arg parsing in a platform agnostic way. + */ +class ToolRunner extends events.EventEmitter { + constructor(toolPath, args, options) { + super(); + if (!toolPath) { + throw new Error("Parameter 'toolPath' cannot be null or empty."); + } + this.toolPath = toolPath; + this.args = args || []; + this.options = options || {}; + } + _debug(message) { + if (this.options.listeners && this.options.listeners.debug) { + this.options.listeners.debug(message); + } + } + _getCommandString(options, noPrefix) { + const toolPath = this._getSpawnFileName(); + const args = this._getSpawnArgs(options); + let cmd = noPrefix ? '' : '[command]'; // omit prefix when piped to a second tool + if (IS_WINDOWS) { + // Windows + cmd file + if (this._isCmdFile()) { + cmd += toolPath; + for (const a of args) { + cmd += ` ${a}`; + } + } + // Windows + verbatim + else if (options.windowsVerbatimArguments) { + cmd += `"${toolPath}"`; + for (const a of args) { + cmd += ` ${a}`; + } + } + // Windows (regular) + else { + cmd += this._windowsQuoteCmdArg(toolPath); + for (const a of args) { + cmd += ` ${this._windowsQuoteCmdArg(a)}`; + } + } + } + else { + // OSX/Linux - this can likely be improved with some form of quoting. + // creating processes on Unix is fundamentally different than Windows. + // on Unix, execvp() takes an arg array. + cmd += toolPath; + for (const a of args) { + cmd += ` ${a}`; + } + } + return cmd; + } + _processLineBuffer(data, strBuffer, onLine) { + try { + let s = strBuffer + data.toString(); + let n = s.indexOf(os.EOL); + while (n > -1) { + const line = s.substring(0, n); + onLine(line); + // the rest of the string ... + s = s.substring(n + os.EOL.length); + n = s.indexOf(os.EOL); + } + return s; + } + catch (err) { + // streaming lines to console is best effort. Don't fail a build. + this._debug(`error processing line. Failed with error ${err}`); + return ''; + } + } + _getSpawnFileName() { + if (IS_WINDOWS) { + if (this._isCmdFile()) { + return process.env['COMSPEC'] || 'cmd.exe'; + } + } + return this.toolPath; + } + _getSpawnArgs(options) { + if (IS_WINDOWS) { + if (this._isCmdFile()) { + let argline = `/D /S /C "${this._windowsQuoteCmdArg(this.toolPath)}`; + for (const a of this.args) { + argline += ' '; + argline += options.windowsVerbatimArguments + ? a + : this._windowsQuoteCmdArg(a); + } + argline += '"'; + return [argline]; + } + } + return this.args; + } + _endsWith(str, end) { + return str.endsWith(end); + } + _isCmdFile() { + const upperToolPath = this.toolPath.toUpperCase(); + return (this._endsWith(upperToolPath, '.CMD') || + this._endsWith(upperToolPath, '.BAT')); + } + _windowsQuoteCmdArg(arg) { + // for .exe, apply the normal quoting rules that libuv applies + if (!this._isCmdFile()) { + return this._uvQuoteCmdArg(arg); + } + // otherwise apply quoting rules specific to the cmd.exe command line parser. + // the libuv rules are generic and are not designed specifically for cmd.exe + // command line parser. + // + // for a detailed description of the cmd.exe command line parser, refer to + // http://stackoverflow.com/questions/4094699/how-does-the-windows-command-interpreter-cmd-exe-parse-scripts/7970912#7970912 + // need quotes for empty arg + if (!arg) { + return '""'; + } + // determine whether the arg needs to be quoted + const cmdSpecialChars = [ + ' ', + '\t', + '&', + '(', + ')', + '[', + ']', + '{', + '}', + '^', + '=', + ';', + '!', + "'", + '+', + ',', + '`', + '~', + '|', + '<', + '>', + '"' + ]; + let needsQuotes = false; + for (const char of arg) { + if (cmdSpecialChars.some(x => x === char)) { + needsQuotes = true; + break; + } + } + // short-circuit if quotes not needed + if (!needsQuotes) { + return arg; + } + // the following quoting rules are very similar to the rules that by libuv applies. + // + // 1) wrap the string in quotes + // + // 2) double-up quotes - i.e. " => "" + // + // this is different from the libuv quoting rules. libuv replaces " with \", which unfortunately + // doesn't work well with a cmd.exe command line. + // + // note, replacing " with "" also works well if the arg is passed to a downstream .NET console app. + // for example, the command line: + // foo.exe "myarg:""my val""" + // is parsed by a .NET console app into an arg array: + // [ "myarg:\"my val\"" ] + // which is the same end result when applying libuv quoting rules. although the actual + // command line from libuv quoting rules would look like: + // foo.exe "myarg:\"my val\"" + // + // 3) double-up slashes that precede a quote, + // e.g. hello \world => "hello \world" + // hello\"world => "hello\\""world" + // hello\\"world => "hello\\\\""world" + // hello world\ => "hello world\\" + // + // technically this is not required for a cmd.exe command line, or the batch argument parser. + // the reasons for including this as a .cmd quoting rule are: + // + // a) this is optimized for the scenario where the argument is passed from the .cmd file to an + // external program. many programs (e.g. .NET console apps) rely on the slash-doubling rule. + // + // b) it's what we've been doing previously (by deferring to node default behavior) and we + // haven't heard any complaints about that aspect. + // + // note, a weakness of the quoting rules chosen here, is that % is not escaped. in fact, % cannot be + // escaped when used on the command line directly - even though within a .cmd file % can be escaped + // by using %%. + // + // the saving grace is, on the command line, %var% is left as-is if var is not defined. this contrasts + // the line parsing rules within a .cmd file, where if var is not defined it is replaced with nothing. + // + // one option that was explored was replacing % with ^% - i.e. %var% => ^%var^%. this hack would + // often work, since it is unlikely that var^ would exist, and the ^ character is removed when the + // variable is used. the problem, however, is that ^ is not removed when %* is used to pass the args + // to an external program. + // + // an unexplored potential solution for the % escaping problem, is to create a wrapper .cmd file. + // % can be escaped within a .cmd file. + let reverse = '"'; + let quoteHit = true; + for (let i = arg.length; i > 0; i--) { + // walk the string in reverse + reverse += arg[i - 1]; + if (quoteHit && arg[i - 1] === '\\') { + reverse += '\\'; // double the slash + } + else if (arg[i - 1] === '"') { + quoteHit = true; + reverse += '"'; // double the quote + } + else { + quoteHit = false; + } + } + reverse += '"'; + return reverse + .split('') + .reverse() + .join(''); + } + _uvQuoteCmdArg(arg) { + // Tool runner wraps child_process.spawn() and needs to apply the same quoting as + // Node in certain cases where the undocumented spawn option windowsVerbatimArguments + // is used. + // + // Since this function is a port of quote_cmd_arg from Node 4.x (technically, lib UV, + // see https://github.com/nodejs/node/blob/v4.x/deps/uv/src/win/process.c for details), + // pasting copyright notice from Node within this function: + // + // Copyright Joyent, Inc. and other Node contributors. All rights reserved. + // + // Permission is hereby granted, free of charge, to any person obtaining a copy + // of this software and associated documentation files (the "Software"), to + // deal in the Software without restriction, including without limitation the + // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + // sell copies of the Software, and to permit persons to whom the Software is + // furnished to do so, subject to the following conditions: + // + // The above copyright notice and this permission notice shall be included in + // all copies or substantial portions of the Software. + // + // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + // IN THE SOFTWARE. + if (!arg) { + // Need double quotation for empty argument + return '""'; + } + if (!arg.includes(' ') && !arg.includes('\t') && !arg.includes('"')) { + // No quotation needed + return arg; + } + if (!arg.includes('"') && !arg.includes('\\')) { + // No embedded double quotes or backslashes, so I can just wrap + // quote marks around the whole thing. + return `"${arg}"`; + } + // Expected input/output: + // input : hello"world + // output: "hello\"world" + // input : hello""world + // output: "hello\"\"world" + // input : hello\world + // output: hello\world + // input : hello\\world + // output: hello\\world + // input : hello\"world + // output: "hello\\\"world" + // input : hello\\"world + // output: "hello\\\\\"world" + // input : hello world\ + // output: "hello world\\" - note the comment in libuv actually reads "hello world\" + // but it appears the comment is wrong, it should be "hello world\\" + let reverse = '"'; + let quoteHit = true; + for (let i = arg.length; i > 0; i--) { + // walk the string in reverse + reverse += arg[i - 1]; + if (quoteHit && arg[i - 1] === '\\') { + reverse += '\\'; + } + else if (arg[i - 1] === '"') { + quoteHit = true; + reverse += '\\'; + } + else { + quoteHit = false; + } + } + reverse += '"'; + return reverse + .split('') + .reverse() + .join(''); + } + _cloneExecOptions(options) { + options = options || {}; + const result = { + cwd: options.cwd || process.cwd(), + env: options.env || process.env, + silent: options.silent || false, + windowsVerbatimArguments: options.windowsVerbatimArguments || false, + failOnStdErr: options.failOnStdErr || false, + ignoreReturnCode: options.ignoreReturnCode || false, + delay: options.delay || 10000 + }; + result.outStream = options.outStream || process.stdout; + result.errStream = options.errStream || process.stderr; + return result; + } + _getSpawnOptions(options, toolPath) { + options = options || {}; + const result = {}; + result.cwd = options.cwd; + result.env = options.env; + result['windowsVerbatimArguments'] = + options.windowsVerbatimArguments || this._isCmdFile(); + if (options.windowsVerbatimArguments) { + result.argv0 = `"${toolPath}"`; + } + return result; + } + /** + * Exec a tool. + * Output will be streamed to the live console. + * Returns promise with return code + * + * @param tool path to tool to exec + * @param options optional exec options. See ExecOptions + * @returns number + */ + exec() { + return __awaiter(this, void 0, void 0, function* () { + // root the tool path if it is unrooted and contains relative pathing + if (!ioUtil.isRooted(this.toolPath) && + (this.toolPath.includes('/') || + (IS_WINDOWS && this.toolPath.includes('\\')))) { + // prefer options.cwd if it is specified, however options.cwd may also need to be rooted + this.toolPath = path.resolve(process.cwd(), this.options.cwd || process.cwd(), this.toolPath); + } + // if the tool is only a file name, then resolve it from the PATH + // otherwise verify it exists (add extension on Windows if necessary) + this.toolPath = yield io.which(this.toolPath, true); + return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () { + this._debug(`exec tool: ${this.toolPath}`); + this._debug('arguments:'); + for (const arg of this.args) { + this._debug(` ${arg}`); + } + const optionsNonNull = this._cloneExecOptions(this.options); + if (!optionsNonNull.silent && optionsNonNull.outStream) { + optionsNonNull.outStream.write(this._getCommandString(optionsNonNull) + os.EOL); + } + const state = new ExecState(optionsNonNull, this.toolPath); + state.on('debug', (message) => { + this._debug(message); + }); + if (this.options.cwd && !(yield ioUtil.exists(this.options.cwd))) { + return reject(new Error(`The cwd: ${this.options.cwd} does not exist!`)); + } + const fileName = this._getSpawnFileName(); + const cp = child.spawn(fileName, this._getSpawnArgs(optionsNonNull), this._getSpawnOptions(this.options, fileName)); + let stdbuffer = ''; + if (cp.stdout) { + cp.stdout.on('data', (data) => { + if (this.options.listeners && this.options.listeners.stdout) { + this.options.listeners.stdout(data); + } + if (!optionsNonNull.silent && optionsNonNull.outStream) { + optionsNonNull.outStream.write(data); + } + stdbuffer = this._processLineBuffer(data, stdbuffer, (line) => { + if (this.options.listeners && this.options.listeners.stdline) { + this.options.listeners.stdline(line); + } + }); + }); + } + let errbuffer = ''; + if (cp.stderr) { + cp.stderr.on('data', (data) => { + state.processStderr = true; + if (this.options.listeners && this.options.listeners.stderr) { + this.options.listeners.stderr(data); + } + if (!optionsNonNull.silent && + optionsNonNull.errStream && + optionsNonNull.outStream) { + const s = optionsNonNull.failOnStdErr + ? optionsNonNull.errStream + : optionsNonNull.outStream; + s.write(data); + } + errbuffer = this._processLineBuffer(data, errbuffer, (line) => { + if (this.options.listeners && this.options.listeners.errline) { + this.options.listeners.errline(line); + } + }); + }); + } + cp.on('error', (err) => { + state.processError = err.message; + state.processExited = true; + state.processClosed = true; + state.CheckComplete(); + }); + cp.on('exit', (code) => { + state.processExitCode = code; + state.processExited = true; + this._debug(`Exit code ${code} received from tool '${this.toolPath}'`); + state.CheckComplete(); + }); + cp.on('close', (code) => { + state.processExitCode = code; + state.processExited = true; + state.processClosed = true; + this._debug(`STDIO streams have closed for tool '${this.toolPath}'`); + state.CheckComplete(); + }); + state.on('done', (error, exitCode) => { + if (stdbuffer.length > 0) { + this.emit('stdline', stdbuffer); + } + if (errbuffer.length > 0) { + this.emit('errline', errbuffer); + } + cp.removeAllListeners(); + if (error) { + reject(error); + } + else { + resolve(exitCode); + } + }); + if (this.options.input) { + if (!cp.stdin) { + throw new Error('child process missing stdin'); + } + cp.stdin.end(this.options.input); + } + })); + }); + } +} +exports.ToolRunner = ToolRunner; +/** + * Convert an arg string to an array of args. Handles escaping + * + * @param argString string of arguments + * @returns string[] array of arguments + */ +function argStringToArray(argString) { + const args = []; + let inQuotes = false; + let escaped = false; + let arg = ''; + function append(c) { + // we only escape double quotes. + if (escaped && c !== '"') { + arg += '\\'; + } + arg += c; + escaped = false; + } + for (let i = 0; i < argString.length; i++) { + const c = argString.charAt(i); + if (c === '"') { + if (!escaped) { + inQuotes = !inQuotes; + } + else { + append(c); + } + continue; + } + if (c === '\\' && escaped) { + append(c); + continue; + } + if (c === '\\' && inQuotes) { + escaped = true; + continue; + } + if (c === ' ' && !inQuotes) { + if (arg.length > 0) { + args.push(arg); + arg = ''; + } + continue; + } + append(c); + } + if (arg.length > 0) { + args.push(arg.trim()); + } + return args; +} +exports.argStringToArray = argStringToArray; +class ExecState extends events.EventEmitter { + constructor(options, toolPath) { + super(); + this.processClosed = false; // tracks whether the process has exited and stdio is closed + this.processError = ''; + this.processExitCode = 0; + this.processExited = false; // tracks whether the process has exited + this.processStderr = false; // tracks whether stderr was written to + this.delay = 10000; // 10 seconds + this.done = false; + this.timeout = null; + if (!toolPath) { + throw new Error('toolPath must not be empty'); + } + this.options = options; + this.toolPath = toolPath; + if (options.delay) { + this.delay = options.delay; + } + } + CheckComplete() { + if (this.done) { + return; + } + if (this.processClosed) { + this._setResult(); + } + else if (this.processExited) { + this.timeout = timers_1.setTimeout(ExecState.HandleTimeout, this.delay, this); + } + } + _debug(message) { + this.emit('debug', message); + } + _setResult() { + // determine whether there is an error + let error; + if (this.processExited) { + if (this.processError) { + error = new Error(`There was an error when attempting to execute the process '${this.toolPath}'. This may indicate the process failed to start. Error: ${this.processError}`); + } + else if (this.processExitCode !== 0 && !this.options.ignoreReturnCode) { + error = new Error(`The process '${this.toolPath}' failed with exit code ${this.processExitCode}`); + } + else if (this.processStderr && this.options.failOnStdErr) { + error = new Error(`The process '${this.toolPath}' failed because one or more lines were written to the STDERR stream`); + } + } + // clear the timeout + if (this.timeout) { + clearTimeout(this.timeout); + this.timeout = null; + } + this.done = true; + this.emit('done', error, this.processExitCode); + } + static HandleTimeout(state) { + if (state.done) { + return; + } + if (!state.processClosed && state.processExited) { + const message = `The STDIO streams did not close within ${state.delay / + 1000} seconds of the exit event from process '${state.toolPath}'. This may indicate a child process inherited the STDIO streams and has not yet exited.`; + state._debug(message); + } + state._setResult(); + } +} +//# sourceMappingURL=toolrunner.js.map + +/***/ }), + +/***/ 7910: +/***/ (function(__unused_webpack_module, exports) { + +"use strict"; + +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.PersonalAccessTokenCredentialHandler = exports.BearerCredentialHandler = exports.BasicCredentialHandler = void 0; +class BasicCredentialHandler { + constructor(username, password) { + this.username = username; + this.password = password; + } + prepareRequest(options) { + if (!options.headers) { + throw Error('The request has no headers'); + } + options.headers['Authorization'] = `Basic ${Buffer.from(`${this.username}:${this.password}`).toString('base64')}`; + } + // This handler cannot handle 401 + canHandleAuthentication() { + return false; + } + handleAuthentication() { + return __awaiter(this, void 0, void 0, function* () { + throw new Error('not implemented'); + }); + } +} +exports.BasicCredentialHandler = BasicCredentialHandler; +class BearerCredentialHandler { + constructor(token) { + this.token = token; + } + // currently implements pre-authorization + // TODO: support preAuth = false where it hooks on 401 + prepareRequest(options) { + if (!options.headers) { + throw Error('The request has no headers'); + } + options.headers['Authorization'] = `Bearer ${this.token}`; + } + // This handler cannot handle 401 + canHandleAuthentication() { + return false; + } + handleAuthentication() { + return __awaiter(this, void 0, void 0, function* () { + throw new Error('not implemented'); + }); + } +} +exports.BearerCredentialHandler = BearerCredentialHandler; +class PersonalAccessTokenCredentialHandler { + constructor(token) { + this.token = token; + } + // currently implements pre-authorization + // TODO: support preAuth = false where it hooks on 401 + prepareRequest(options) { + if (!options.headers) { + throw Error('The request has no headers'); + } + options.headers['Authorization'] = `Basic ${Buffer.from(`PAT:${this.token}`).toString('base64')}`; + } + // This handler cannot handle 401 + canHandleAuthentication() { + return false; + } + handleAuthentication() { + return __awaiter(this, void 0, void 0, function* () { + throw new Error('not implemented'); + }); + } +} +exports.PersonalAccessTokenCredentialHandler = PersonalAccessTokenCredentialHandler; +//# sourceMappingURL=auth.js.map + +/***/ }), + +/***/ 5753: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +/* eslint-disable @typescript-eslint/no-explicit-any */ +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.HttpClient = exports.isHttps = exports.HttpClientResponse = exports.HttpClientError = exports.getProxyUrl = exports.MediaTypes = exports.Headers = exports.HttpCodes = void 0; +const http = __importStar(__nccwpck_require__(3685)); +const https = __importStar(__nccwpck_require__(5687)); +const pm = __importStar(__nccwpck_require__(2499)); +const tunnel = __importStar(__nccwpck_require__(8672)); +const undici_1 = __nccwpck_require__(7364); +var HttpCodes; +(function (HttpCodes) { + HttpCodes[HttpCodes["OK"] = 200] = "OK"; + HttpCodes[HttpCodes["MultipleChoices"] = 300] = "MultipleChoices"; + HttpCodes[HttpCodes["MovedPermanently"] = 301] = "MovedPermanently"; + HttpCodes[HttpCodes["ResourceMoved"] = 302] = "ResourceMoved"; + HttpCodes[HttpCodes["SeeOther"] = 303] = "SeeOther"; + HttpCodes[HttpCodes["NotModified"] = 304] = "NotModified"; + HttpCodes[HttpCodes["UseProxy"] = 305] = "UseProxy"; + HttpCodes[HttpCodes["SwitchProxy"] = 306] = "SwitchProxy"; + HttpCodes[HttpCodes["TemporaryRedirect"] = 307] = "TemporaryRedirect"; + HttpCodes[HttpCodes["PermanentRedirect"] = 308] = "PermanentRedirect"; + HttpCodes[HttpCodes["BadRequest"] = 400] = "BadRequest"; + HttpCodes[HttpCodes["Unauthorized"] = 401] = "Unauthorized"; + HttpCodes[HttpCodes["PaymentRequired"] = 402] = "PaymentRequired"; + HttpCodes[HttpCodes["Forbidden"] = 403] = "Forbidden"; + HttpCodes[HttpCodes["NotFound"] = 404] = "NotFound"; + HttpCodes[HttpCodes["MethodNotAllowed"] = 405] = "MethodNotAllowed"; + HttpCodes[HttpCodes["NotAcceptable"] = 406] = "NotAcceptable"; + HttpCodes[HttpCodes["ProxyAuthenticationRequired"] = 407] = "ProxyAuthenticationRequired"; + HttpCodes[HttpCodes["RequestTimeout"] = 408] = "RequestTimeout"; + HttpCodes[HttpCodes["Conflict"] = 409] = "Conflict"; + HttpCodes[HttpCodes["Gone"] = 410] = "Gone"; + HttpCodes[HttpCodes["TooManyRequests"] = 429] = "TooManyRequests"; + HttpCodes[HttpCodes["InternalServerError"] = 500] = "InternalServerError"; + HttpCodes[HttpCodes["NotImplemented"] = 501] = "NotImplemented"; + HttpCodes[HttpCodes["BadGateway"] = 502] = "BadGateway"; + HttpCodes[HttpCodes["ServiceUnavailable"] = 503] = "ServiceUnavailable"; + HttpCodes[HttpCodes["GatewayTimeout"] = 504] = "GatewayTimeout"; +})(HttpCodes || (exports.HttpCodes = HttpCodes = {})); +var Headers; +(function (Headers) { + Headers["Accept"] = "accept"; + Headers["ContentType"] = "content-type"; +})(Headers || (exports.Headers = Headers = {})); +var MediaTypes; +(function (MediaTypes) { + MediaTypes["ApplicationJson"] = "application/json"; +})(MediaTypes || (exports.MediaTypes = MediaTypes = {})); +/** + * Returns the proxy URL, depending upon the supplied url and proxy environment variables. + * @param serverUrl The server URL where the request will be sent. For example, https://api.github.com + */ +function getProxyUrl(serverUrl) { + const proxyUrl = pm.getProxyUrl(new URL(serverUrl)); + return proxyUrl ? proxyUrl.href : ''; +} +exports.getProxyUrl = getProxyUrl; +const HttpRedirectCodes = [ + HttpCodes.MovedPermanently, + HttpCodes.ResourceMoved, + HttpCodes.SeeOther, + HttpCodes.TemporaryRedirect, + HttpCodes.PermanentRedirect +]; +const HttpResponseRetryCodes = [ + HttpCodes.BadGateway, + HttpCodes.ServiceUnavailable, + HttpCodes.GatewayTimeout +]; +const RetryableHttpVerbs = ['OPTIONS', 'GET', 'DELETE', 'HEAD']; +const ExponentialBackoffCeiling = 10; +const ExponentialBackoffTimeSlice = 5; +class HttpClientError extends Error { + constructor(message, statusCode) { + super(message); + this.name = 'HttpClientError'; + this.statusCode = statusCode; + Object.setPrototypeOf(this, HttpClientError.prototype); + } +} +exports.HttpClientError = HttpClientError; +class HttpClientResponse { + constructor(message) { + this.message = message; + } + readBody() { + return __awaiter(this, void 0, void 0, function* () { + return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () { + let output = Buffer.alloc(0); + this.message.on('data', (chunk) => { + output = Buffer.concat([output, chunk]); + }); + this.message.on('end', () => { + resolve(output.toString()); + }); + })); + }); + } + readBodyBuffer() { + return __awaiter(this, void 0, void 0, function* () { + return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () { + const chunks = []; + this.message.on('data', (chunk) => { + chunks.push(chunk); + }); + this.message.on('end', () => { + resolve(Buffer.concat(chunks)); + }); + })); + }); + } +} +exports.HttpClientResponse = HttpClientResponse; +function isHttps(requestUrl) { + const parsedUrl = new URL(requestUrl); + return parsedUrl.protocol === 'https:'; +} +exports.isHttps = isHttps; +class HttpClient { + constructor(userAgent, handlers, requestOptions) { + this._ignoreSslError = false; + this._allowRedirects = true; + this._allowRedirectDowngrade = false; + this._maxRedirects = 50; + this._allowRetries = false; + this._maxRetries = 1; + this._keepAlive = false; + this._disposed = false; + this.userAgent = userAgent; + this.handlers = handlers || []; + this.requestOptions = requestOptions; + if (requestOptions) { + if (requestOptions.ignoreSslError != null) { + this._ignoreSslError = requestOptions.ignoreSslError; + } + this._socketTimeout = requestOptions.socketTimeout; + if (requestOptions.allowRedirects != null) { + this._allowRedirects = requestOptions.allowRedirects; + } + if (requestOptions.allowRedirectDowngrade != null) { + this._allowRedirectDowngrade = requestOptions.allowRedirectDowngrade; + } + if (requestOptions.maxRedirects != null) { + this._maxRedirects = Math.max(requestOptions.maxRedirects, 0); + } + if (requestOptions.keepAlive != null) { + this._keepAlive = requestOptions.keepAlive; + } + if (requestOptions.allowRetries != null) { + this._allowRetries = requestOptions.allowRetries; + } + if (requestOptions.maxRetries != null) { + this._maxRetries = requestOptions.maxRetries; + } + } + } + options(requestUrl, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('OPTIONS', requestUrl, null, additionalHeaders || {}); + }); + } + get(requestUrl, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('GET', requestUrl, null, additionalHeaders || {}); + }); + } + del(requestUrl, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('DELETE', requestUrl, null, additionalHeaders || {}); + }); + } + post(requestUrl, data, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('POST', requestUrl, data, additionalHeaders || {}); + }); + } + patch(requestUrl, data, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('PATCH', requestUrl, data, additionalHeaders || {}); + }); + } + put(requestUrl, data, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('PUT', requestUrl, data, additionalHeaders || {}); + }); + } + head(requestUrl, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('HEAD', requestUrl, null, additionalHeaders || {}); + }); + } + sendStream(verb, requestUrl, stream, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request(verb, requestUrl, stream, additionalHeaders); + }); + } + /** + * Gets a typed object from an endpoint + * Be aware that not found returns a null. Other errors (4xx, 5xx) reject the promise + */ + getJson(requestUrl, additionalHeaders = {}) { + return __awaiter(this, void 0, void 0, function* () { + additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); + const res = yield this.get(requestUrl, additionalHeaders); + return this._processResponse(res, this.requestOptions); + }); + } + postJson(requestUrl, obj, additionalHeaders = {}) { + return __awaiter(this, void 0, void 0, function* () { + const data = JSON.stringify(obj, null, 2); + additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); + additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson); + const res = yield this.post(requestUrl, data, additionalHeaders); + return this._processResponse(res, this.requestOptions); + }); + } + putJson(requestUrl, obj, additionalHeaders = {}) { + return __awaiter(this, void 0, void 0, function* () { + const data = JSON.stringify(obj, null, 2); + additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); + additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson); + const res = yield this.put(requestUrl, data, additionalHeaders); + return this._processResponse(res, this.requestOptions); + }); + } + patchJson(requestUrl, obj, additionalHeaders = {}) { + return __awaiter(this, void 0, void 0, function* () { + const data = JSON.stringify(obj, null, 2); + additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); + additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson); + const res = yield this.patch(requestUrl, data, additionalHeaders); + return this._processResponse(res, this.requestOptions); + }); + } + /** + * Makes a raw http request. + * All other methods such as get, post, patch, and request ultimately call this. + * Prefer get, del, post and patch + */ + request(verb, requestUrl, data, headers) { + return __awaiter(this, void 0, void 0, function* () { + if (this._disposed) { + throw new Error('Client has already been disposed.'); + } + const parsedUrl = new URL(requestUrl); + let info = this._prepareRequest(verb, parsedUrl, headers); + // Only perform retries on reads since writes may not be idempotent. + const maxTries = this._allowRetries && RetryableHttpVerbs.includes(verb) + ? this._maxRetries + 1 + : 1; + let numTries = 0; + let response; + do { + response = yield this.requestRaw(info, data); + // Check if it's an authentication challenge + if (response && + response.message && + response.message.statusCode === HttpCodes.Unauthorized) { + let authenticationHandler; + for (const handler of this.handlers) { + if (handler.canHandleAuthentication(response)) { + authenticationHandler = handler; + break; + } + } + if (authenticationHandler) { + return authenticationHandler.handleAuthentication(this, info, data); + } + else { + // We have received an unauthorized response but have no handlers to handle it. + // Let the response return to the caller. + return response; + } + } + let redirectsRemaining = this._maxRedirects; + while (response.message.statusCode && + HttpRedirectCodes.includes(response.message.statusCode) && + this._allowRedirects && + redirectsRemaining > 0) { + const redirectUrl = response.message.headers['location']; + if (!redirectUrl) { + // if there's no location to redirect to, we won't + break; + } + const parsedRedirectUrl = new URL(redirectUrl); + if (parsedUrl.protocol === 'https:' && + parsedUrl.protocol !== parsedRedirectUrl.protocol && + !this._allowRedirectDowngrade) { + throw new Error('Redirect from HTTPS to HTTP protocol. This downgrade is not allowed for security reasons. If you want to allow this behavior, set the allowRedirectDowngrade option to true.'); + } + // we need to finish reading the response before reassigning response + // which will leak the open socket. + yield response.readBody(); + // strip authorization header if redirected to a different hostname + if (parsedRedirectUrl.hostname !== parsedUrl.hostname) { + for (const header in headers) { + // header names are case insensitive + if (header.toLowerCase() === 'authorization') { + delete headers[header]; + } + } + } + // let's make the request with the new redirectUrl + info = this._prepareRequest(verb, parsedRedirectUrl, headers); + response = yield this.requestRaw(info, data); + redirectsRemaining--; + } + if (!response.message.statusCode || + !HttpResponseRetryCodes.includes(response.message.statusCode)) { + // If not a retry code, return immediately instead of retrying + return response; + } + numTries += 1; + if (numTries < maxTries) { + yield response.readBody(); + yield this._performExponentialBackoff(numTries); + } + } while (numTries < maxTries); + return response; + }); + } + /** + * Needs to be called if keepAlive is set to true in request options. + */ + dispose() { + if (this._agent) { + this._agent.destroy(); + } + this._disposed = true; + } + /** + * Raw request. + * @param info + * @param data + */ + requestRaw(info, data) { + return __awaiter(this, void 0, void 0, function* () { + return new Promise((resolve, reject) => { + function callbackForResult(err, res) { + if (err) { + reject(err); + } + else if (!res) { + // If `err` is not passed, then `res` must be passed. + reject(new Error('Unknown error')); + } + else { + resolve(res); + } + } + this.requestRawWithCallback(info, data, callbackForResult); + }); + }); + } + /** + * Raw request with callback. + * @param info + * @param data + * @param onResult + */ + requestRawWithCallback(info, data, onResult) { + if (typeof data === 'string') { + if (!info.options.headers) { + info.options.headers = {}; + } + info.options.headers['Content-Length'] = Buffer.byteLength(data, 'utf8'); + } + let callbackCalled = false; + function handleResult(err, res) { + if (!callbackCalled) { + callbackCalled = true; + onResult(err, res); + } + } + const req = info.httpModule.request(info.options, (msg) => { + const res = new HttpClientResponse(msg); + handleResult(undefined, res); + }); + let socket; + req.on('socket', sock => { + socket = sock; + }); + // If we ever get disconnected, we want the socket to timeout eventually + req.setTimeout(this._socketTimeout || 3 * 60000, () => { + if (socket) { + socket.end(); + } + handleResult(new Error(`Request timeout: ${info.options.path}`)); + }); + req.on('error', function (err) { + // err has statusCode property + // res should have headers + handleResult(err); + }); + if (data && typeof data === 'string') { + req.write(data, 'utf8'); + } + if (data && typeof data !== 'string') { + data.on('close', function () { + req.end(); + }); + data.pipe(req); + } + else { + req.end(); + } + } + /** + * Gets an http agent. This function is useful when you need an http agent that handles + * routing through a proxy server - depending upon the url and proxy environment variables. + * @param serverUrl The server URL where the request will be sent. For example, https://api.github.com + */ + getAgent(serverUrl) { + const parsedUrl = new URL(serverUrl); + return this._getAgent(parsedUrl); + } + getAgentDispatcher(serverUrl) { + const parsedUrl = new URL(serverUrl); + const proxyUrl = pm.getProxyUrl(parsedUrl); + const useProxy = proxyUrl && proxyUrl.hostname; + if (!useProxy) { + return; + } + return this._getProxyAgentDispatcher(parsedUrl, proxyUrl); + } + _prepareRequest(method, requestUrl, headers) { + const info = {}; + info.parsedUrl = requestUrl; + const usingSsl = info.parsedUrl.protocol === 'https:'; + info.httpModule = usingSsl ? https : http; + const defaultPort = usingSsl ? 443 : 80; + info.options = {}; + info.options.host = info.parsedUrl.hostname; + info.options.port = info.parsedUrl.port + ? parseInt(info.parsedUrl.port) + : defaultPort; + info.options.path = + (info.parsedUrl.pathname || '') + (info.parsedUrl.search || ''); + info.options.method = method; + info.options.headers = this._mergeHeaders(headers); + if (this.userAgent != null) { + info.options.headers['user-agent'] = this.userAgent; + } + info.options.agent = this._getAgent(info.parsedUrl); + // gives handlers an opportunity to participate + if (this.handlers) { + for (const handler of this.handlers) { + handler.prepareRequest(info.options); + } + } + return info; + } + _mergeHeaders(headers) { + if (this.requestOptions && this.requestOptions.headers) { + return Object.assign({}, lowercaseKeys(this.requestOptions.headers), lowercaseKeys(headers || {})); + } + return lowercaseKeys(headers || {}); + } + _getExistingOrDefaultHeader(additionalHeaders, header, _default) { + let clientHeader; + if (this.requestOptions && this.requestOptions.headers) { + clientHeader = lowercaseKeys(this.requestOptions.headers)[header]; + } + return additionalHeaders[header] || clientHeader || _default; + } + _getAgent(parsedUrl) { + let agent; + const proxyUrl = pm.getProxyUrl(parsedUrl); + const useProxy = proxyUrl && proxyUrl.hostname; + if (this._keepAlive && useProxy) { + agent = this._proxyAgent; + } + if (this._keepAlive && !useProxy) { + agent = this._agent; + } + // if agent is already assigned use that agent. + if (agent) { + return agent; + } + const usingSsl = parsedUrl.protocol === 'https:'; + let maxSockets = 100; + if (this.requestOptions) { + maxSockets = this.requestOptions.maxSockets || http.globalAgent.maxSockets; + } + // This is `useProxy` again, but we need to check `proxyURl` directly for TypeScripts's flow analysis. + if (proxyUrl && proxyUrl.hostname) { + const agentOptions = { + maxSockets, + keepAlive: this._keepAlive, + proxy: Object.assign(Object.assign({}, ((proxyUrl.username || proxyUrl.password) && { + proxyAuth: `${proxyUrl.username}:${proxyUrl.password}` + })), { host: proxyUrl.hostname, port: proxyUrl.port }) + }; + let tunnelAgent; + const overHttps = proxyUrl.protocol === 'https:'; + if (usingSsl) { + tunnelAgent = overHttps ? tunnel.httpsOverHttps : tunnel.httpsOverHttp; + } + else { + tunnelAgent = overHttps ? tunnel.httpOverHttps : tunnel.httpOverHttp; + } + agent = tunnelAgent(agentOptions); + this._proxyAgent = agent; + } + // if reusing agent across request and tunneling agent isn't assigned create a new agent + if (this._keepAlive && !agent) { + const options = { keepAlive: this._keepAlive, maxSockets }; + agent = usingSsl ? new https.Agent(options) : new http.Agent(options); + this._agent = agent; + } + // if not using private agent and tunnel agent isn't setup then use global agent + if (!agent) { + agent = usingSsl ? https.globalAgent : http.globalAgent; + } + if (usingSsl && this._ignoreSslError) { + // we don't want to set NODE_TLS_REJECT_UNAUTHORIZED=0 since that will affect request for entire process + // http.RequestOptions doesn't expose a way to modify RequestOptions.agent.options + // we have to cast it to any and change it directly + agent.options = Object.assign(agent.options || {}, { + rejectUnauthorized: false + }); + } + return agent; + } + _getProxyAgentDispatcher(parsedUrl, proxyUrl) { + let proxyAgent; + if (this._keepAlive) { + proxyAgent = this._proxyAgentDispatcher; + } + // if agent is already assigned use that agent. + if (proxyAgent) { + return proxyAgent; + } + const usingSsl = parsedUrl.protocol === 'https:'; + proxyAgent = new undici_1.ProxyAgent(Object.assign({ uri: proxyUrl.href, pipelining: !this._keepAlive ? 0 : 1 }, ((proxyUrl.username || proxyUrl.password) && { + token: `${proxyUrl.username}:${proxyUrl.password}` + }))); + this._proxyAgentDispatcher = proxyAgent; + if (usingSsl && this._ignoreSslError) { + // we don't want to set NODE_TLS_REJECT_UNAUTHORIZED=0 since that will affect request for entire process + // http.RequestOptions doesn't expose a way to modify RequestOptions.agent.options + // we have to cast it to any and change it directly + proxyAgent.options = Object.assign(proxyAgent.options.requestTls || {}, { + rejectUnauthorized: false + }); + } + return proxyAgent; + } + _performExponentialBackoff(retryNumber) { + return __awaiter(this, void 0, void 0, function* () { + retryNumber = Math.min(ExponentialBackoffCeiling, retryNumber); + const ms = ExponentialBackoffTimeSlice * Math.pow(2, retryNumber); + return new Promise(resolve => setTimeout(() => resolve(), ms)); + }); + } + _processResponse(res, options) { + return __awaiter(this, void 0, void 0, function* () { + return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () { + const statusCode = res.message.statusCode || 0; + const response = { + statusCode, + result: null, + headers: {} + }; + // not found leads to null obj returned + if (statusCode === HttpCodes.NotFound) { + resolve(response); + } + // get the result from the body + function dateTimeDeserializer(key, value) { + if (typeof value === 'string') { + const a = new Date(value); + if (!isNaN(a.valueOf())) { + return a; + } + } + return value; + } + let obj; + let contents; + try { + contents = yield res.readBody(); + if (contents && contents.length > 0) { + if (options && options.deserializeDates) { + obj = JSON.parse(contents, dateTimeDeserializer); + } + else { + obj = JSON.parse(contents); + } + response.result = obj; + } + response.headers = res.message.headers; + } + catch (err) { + // Invalid resource (contents not json); leaving result obj null + } + // note that 3xx redirects are handled by the http layer. + if (statusCode > 299) { + let msg; + // if exception/error in body, attempt to get better error + if (obj && obj.message) { + msg = obj.message; + } + else if (contents && contents.length > 0) { + // it may be the case that the exception is in the body message as string + msg = contents; + } + else { + msg = `Failed request: (${statusCode})`; + } + const err = new HttpClientError(msg, statusCode); + err.result = response.result; + reject(err); + } + else { + resolve(response); + } + })); + }); + } +} +exports.HttpClient = HttpClient; +const lowercaseKeys = (obj) => Object.keys(obj).reduce((c, k) => ((c[k.toLowerCase()] = obj[k]), c), {}); +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 2499: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.checkBypass = exports.getProxyUrl = void 0; +function getProxyUrl(reqUrl) { + const usingSsl = reqUrl.protocol === 'https:'; + if (checkBypass(reqUrl)) { + return undefined; + } + const proxyVar = (() => { + if (usingSsl) { + return process.env['https_proxy'] || process.env['HTTPS_PROXY']; + } + else { + return process.env['http_proxy'] || process.env['HTTP_PROXY']; + } + })(); + if (proxyVar) { + try { + return new URL(proxyVar); + } + catch (_a) { + if (!proxyVar.startsWith('http://') && !proxyVar.startsWith('https://')) + return new URL(`http://${proxyVar}`); + } + } + else { + return undefined; + } +} +exports.getProxyUrl = getProxyUrl; +function checkBypass(reqUrl) { + if (!reqUrl.hostname) { + return false; + } + const reqHost = reqUrl.hostname; + if (isLoopbackAddress(reqHost)) { + return true; + } + const noProxy = process.env['no_proxy'] || process.env['NO_PROXY'] || ''; + if (!noProxy) { + return false; + } + // Determine the request port + let reqPort; + if (reqUrl.port) { + reqPort = Number(reqUrl.port); + } + else if (reqUrl.protocol === 'http:') { + reqPort = 80; + } + else if (reqUrl.protocol === 'https:') { + reqPort = 443; + } + // Format the request hostname and hostname with port + const upperReqHosts = [reqUrl.hostname.toUpperCase()]; + if (typeof reqPort === 'number') { + upperReqHosts.push(`${upperReqHosts[0]}:${reqPort}`); + } + // Compare request host against noproxy + for (const upperNoProxyItem of noProxy + .split(',') + .map(x => x.trim().toUpperCase()) + .filter(x => x)) { + if (upperNoProxyItem === '*' || + upperReqHosts.some(x => x === upperNoProxyItem || + x.endsWith(`.${upperNoProxyItem}`) || + (upperNoProxyItem.startsWith('.') && + x.endsWith(`${upperNoProxyItem}`)))) { + return true; + } + } + return false; +} +exports.checkBypass = checkBypass; +function isLoopbackAddress(host) { + const hostLower = host.toLowerCase(); + return (hostLower === 'localhost' || + hostLower.startsWith('127.') || + hostLower.startsWith('[::1]') || + hostLower.startsWith('[0:0:0:0:0:0:0:1]')); +} +//# sourceMappingURL=proxy.js.map + +/***/ }), + +/***/ 8798: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var _a; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getCmdPath = exports.tryGetExecutablePath = exports.isRooted = exports.isDirectory = exports.exists = exports.READONLY = exports.UV_FS_O_EXLOCK = exports.IS_WINDOWS = exports.unlink = exports.symlink = exports.stat = exports.rmdir = exports.rm = exports.rename = exports.readlink = exports.readdir = exports.open = exports.mkdir = exports.lstat = exports.copyFile = exports.chmod = void 0; +const fs = __importStar(__nccwpck_require__(7147)); +const path = __importStar(__nccwpck_require__(1017)); +_a = fs.promises +// export const {open} = 'fs' +, exports.chmod = _a.chmod, exports.copyFile = _a.copyFile, exports.lstat = _a.lstat, exports.mkdir = _a.mkdir, exports.open = _a.open, exports.readdir = _a.readdir, exports.readlink = _a.readlink, exports.rename = _a.rename, exports.rm = _a.rm, exports.rmdir = _a.rmdir, exports.stat = _a.stat, exports.symlink = _a.symlink, exports.unlink = _a.unlink; +// export const {open} = 'fs' +exports.IS_WINDOWS = process.platform === 'win32'; +// See https://github.com/nodejs/node/blob/d0153aee367422d0858105abec186da4dff0a0c5/deps/uv/include/uv/win.h#L691 +exports.UV_FS_O_EXLOCK = 0x10000000; +exports.READONLY = fs.constants.O_RDONLY; +function exists(fsPath) { + return __awaiter(this, void 0, void 0, function* () { + try { + yield exports.stat(fsPath); + } + catch (err) { + if (err.code === 'ENOENT') { + return false; + } + throw err; + } + return true; + }); +} +exports.exists = exists; +function isDirectory(fsPath, useStat = false) { + return __awaiter(this, void 0, void 0, function* () { + const stats = useStat ? yield exports.stat(fsPath) : yield exports.lstat(fsPath); + return stats.isDirectory(); + }); +} +exports.isDirectory = isDirectory; +/** + * On OSX/Linux, true if path starts with '/'. On Windows, true for paths like: + * \, \hello, \\hello\share, C:, and C:\hello (and corresponding alternate separator cases). + */ +function isRooted(p) { + p = normalizeSeparators(p); + if (!p) { + throw new Error('isRooted() parameter "p" cannot be empty'); + } + if (exports.IS_WINDOWS) { + return (p.startsWith('\\') || /^[A-Z]:/i.test(p) // e.g. \ or \hello or \\hello + ); // e.g. C: or C:\hello + } + return p.startsWith('/'); +} +exports.isRooted = isRooted; +/** + * Best effort attempt to determine whether a file exists and is executable. + * @param filePath file path to check + * @param extensions additional file extensions to try + * @return if file exists and is executable, returns the file path. otherwise empty string. + */ +function tryGetExecutablePath(filePath, extensions) { + return __awaiter(this, void 0, void 0, function* () { + let stats = undefined; + try { + // test file exists + stats = yield exports.stat(filePath); + } + catch (err) { + if (err.code !== 'ENOENT') { + // eslint-disable-next-line no-console + console.log(`Unexpected error attempting to determine if executable file exists '${filePath}': ${err}`); + } + } + if (stats && stats.isFile()) { + if (exports.IS_WINDOWS) { + // on Windows, test for valid extension + const upperExt = path.extname(filePath).toUpperCase(); + if (extensions.some(validExt => validExt.toUpperCase() === upperExt)) { + return filePath; + } + } + else { + if (isUnixExecutable(stats)) { + return filePath; + } + } + } + // try each extension + const originalFilePath = filePath; + for (const extension of extensions) { + filePath = originalFilePath + extension; + stats = undefined; + try { + stats = yield exports.stat(filePath); + } + catch (err) { + if (err.code !== 'ENOENT') { + // eslint-disable-next-line no-console + console.log(`Unexpected error attempting to determine if executable file exists '${filePath}': ${err}`); + } + } + if (stats && stats.isFile()) { + if (exports.IS_WINDOWS) { + // preserve the case of the actual file (since an extension was appended) + try { + const directory = path.dirname(filePath); + const upperName = path.basename(filePath).toUpperCase(); + for (const actualName of yield exports.readdir(directory)) { + if (upperName === actualName.toUpperCase()) { + filePath = path.join(directory, actualName); + break; + } + } + } + catch (err) { + // eslint-disable-next-line no-console + console.log(`Unexpected error attempting to determine the actual case of the file '${filePath}': ${err}`); + } + return filePath; + } + else { + if (isUnixExecutable(stats)) { + return filePath; + } + } + } + } + return ''; + }); +} +exports.tryGetExecutablePath = tryGetExecutablePath; +function normalizeSeparators(p) { + p = p || ''; + if (exports.IS_WINDOWS) { + // convert slashes on Windows + p = p.replace(/\//g, '\\'); + // remove redundant slashes + return p.replace(/\\\\+/g, '\\'); + } + // remove redundant slashes + return p.replace(/\/\/+/g, '/'); +} +// on Mac/Linux, test the execute bit +// R W X R W X R W X +// 256 128 64 32 16 8 4 2 1 +function isUnixExecutable(stats) { + return ((stats.mode & 1) > 0 || + ((stats.mode & 8) > 0 && stats.gid === process.getgid()) || + ((stats.mode & 64) > 0 && stats.uid === process.getuid())); +} +// Get the path of cmd.exe in windows +function getCmdPath() { + var _a; + return (_a = process.env['COMSPEC']) !== null && _a !== void 0 ? _a : `cmd.exe`; +} +exports.getCmdPath = getCmdPath; +//# sourceMappingURL=io-util.js.map + +/***/ }), + +/***/ 4721: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.findInPath = exports.which = exports.mkdirP = exports.rmRF = exports.mv = exports.cp = void 0; +const assert_1 = __nccwpck_require__(9491); +const path = __importStar(__nccwpck_require__(1017)); +const ioUtil = __importStar(__nccwpck_require__(8798)); +/** + * Copies a file or folder. + * Based off of shelljs - https://github.com/shelljs/shelljs/blob/9237f66c52e5daa40458f94f9565e18e8132f5a6/src/cp.js + * + * @param source source path + * @param dest destination path + * @param options optional. See CopyOptions. + */ +function cp(source, dest, options = {}) { + return __awaiter(this, void 0, void 0, function* () { + const { force, recursive, copySourceDirectory } = readCopyOptions(options); + const destStat = (yield ioUtil.exists(dest)) ? yield ioUtil.stat(dest) : null; + // Dest is an existing file, but not forcing + if (destStat && destStat.isFile() && !force) { + return; + } + // If dest is an existing directory, should copy inside. + const newDest = destStat && destStat.isDirectory() && copySourceDirectory + ? path.join(dest, path.basename(source)) + : dest; + if (!(yield ioUtil.exists(source))) { + throw new Error(`no such file or directory: ${source}`); + } + const sourceStat = yield ioUtil.stat(source); + if (sourceStat.isDirectory()) { + if (!recursive) { + throw new Error(`Failed to copy. ${source} is a directory, but tried to copy without recursive flag.`); + } + else { + yield cpDirRecursive(source, newDest, 0, force); + } + } + else { + if (path.relative(source, newDest) === '') { + // a file cannot be copied to itself + throw new Error(`'${newDest}' and '${source}' are the same file`); + } + yield copyFile(source, newDest, force); + } + }); +} +exports.cp = cp; +/** + * Moves a path. + * + * @param source source path + * @param dest destination path + * @param options optional. See MoveOptions. + */ +function mv(source, dest, options = {}) { + return __awaiter(this, void 0, void 0, function* () { + if (yield ioUtil.exists(dest)) { + let destExists = true; + if (yield ioUtil.isDirectory(dest)) { + // If dest is directory copy src into dest + dest = path.join(dest, path.basename(source)); + destExists = yield ioUtil.exists(dest); + } + if (destExists) { + if (options.force == null || options.force) { + yield rmRF(dest); + } + else { + throw new Error('Destination already exists'); + } + } + } + yield mkdirP(path.dirname(dest)); + yield ioUtil.rename(source, dest); + }); +} +exports.mv = mv; +/** + * Remove a path recursively with force + * + * @param inputPath path to remove + */ +function rmRF(inputPath) { + return __awaiter(this, void 0, void 0, function* () { + if (ioUtil.IS_WINDOWS) { + // Check for invalid characters + // https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file + if (/[*"<>|]/.test(inputPath)) { + throw new Error('File path must not contain `*`, `"`, `<`, `>` or `|` on Windows'); + } + } + try { + // note if path does not exist, error is silent + yield ioUtil.rm(inputPath, { + force: true, + maxRetries: 3, + recursive: true, + retryDelay: 300 + }); + } + catch (err) { + throw new Error(`File was unable to be removed ${err}`); + } + }); +} +exports.rmRF = rmRF; +/** + * Make a directory. Creates the full path with folders in between + * Will throw if it fails + * + * @param fsPath path to create + * @returns Promise + */ +function mkdirP(fsPath) { + return __awaiter(this, void 0, void 0, function* () { + assert_1.ok(fsPath, 'a path argument must be provided'); + yield ioUtil.mkdir(fsPath, { recursive: true }); + }); +} +exports.mkdirP = mkdirP; +/** + * Returns path of a tool had the tool actually been invoked. Resolves via paths. + * If you check and the tool does not exist, it will throw. + * + * @param tool name of the tool + * @param check whether to check if tool exists + * @returns Promise path to tool + */ +function which(tool, check) { + return __awaiter(this, void 0, void 0, function* () { + if (!tool) { + throw new Error("parameter 'tool' is required"); + } + // recursive when check=true + if (check) { + const result = yield which(tool, false); + if (!result) { + if (ioUtil.IS_WINDOWS) { + throw new Error(`Unable to locate executable file: ${tool}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also verify the file has a valid extension for an executable file.`); + } + else { + throw new Error(`Unable to locate executable file: ${tool}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also check the file mode to verify the file is executable.`); + } + } + return result; + } + const matches = yield findInPath(tool); + if (matches && matches.length > 0) { + return matches[0]; + } + return ''; + }); +} +exports.which = which; +/** + * Returns a list of all occurrences of the given tool on the system path. + * + * @returns Promise the paths of the tool + */ +function findInPath(tool) { + return __awaiter(this, void 0, void 0, function* () { + if (!tool) { + throw new Error("parameter 'tool' is required"); + } + // build the list of extensions to try + const extensions = []; + if (ioUtil.IS_WINDOWS && process.env['PATHEXT']) { + for (const extension of process.env['PATHEXT'].split(path.delimiter)) { + if (extension) { + extensions.push(extension); + } + } + } + // if it's rooted, return it if exists. otherwise return empty. + if (ioUtil.isRooted(tool)) { + const filePath = yield ioUtil.tryGetExecutablePath(tool, extensions); + if (filePath) { + return [filePath]; + } + return []; + } + // if any path separators, return empty + if (tool.includes(path.sep)) { + return []; + } + // build the list of directories + // + // Note, technically "where" checks the current directory on Windows. From a toolkit perspective, + // it feels like we should not do this. Checking the current directory seems like more of a use + // case of a shell, and the which() function exposed by the toolkit should strive for consistency + // across platforms. + const directories = []; + if (process.env.PATH) { + for (const p of process.env.PATH.split(path.delimiter)) { + if (p) { + directories.push(p); + } + } + } + // find all matches + const matches = []; + for (const directory of directories) { + const filePath = yield ioUtil.tryGetExecutablePath(path.join(directory, tool), extensions); + if (filePath) { + matches.push(filePath); + } + } + return matches; + }); +} +exports.findInPath = findInPath; +function readCopyOptions(options) { + const force = options.force == null ? true : options.force; + const recursive = Boolean(options.recursive); + const copySourceDirectory = options.copySourceDirectory == null + ? true + : Boolean(options.copySourceDirectory); + return { force, recursive, copySourceDirectory }; +} +function cpDirRecursive(sourceDir, destDir, currentDepth, force) { + return __awaiter(this, void 0, void 0, function* () { + // Ensure there is not a run away recursive copy + if (currentDepth >= 255) + return; + currentDepth++; + yield mkdirP(destDir); + const files = yield ioUtil.readdir(sourceDir); + for (const fileName of files) { + const srcFile = `${sourceDir}/${fileName}`; + const destFile = `${destDir}/${fileName}`; + const srcFileStat = yield ioUtil.lstat(srcFile); + if (srcFileStat.isDirectory()) { + // Recurse + yield cpDirRecursive(srcFile, destFile, currentDepth, force); + } + else { + yield copyFile(srcFile, destFile, force); + } + } + // Change the mode for the newly created directory + yield ioUtil.chmod(destDir, (yield ioUtil.stat(sourceDir)).mode); + }); +} +// Buffered file copy +function copyFile(srcFile, destFile, force) { + return __awaiter(this, void 0, void 0, function* () { + if ((yield ioUtil.lstat(srcFile)).isSymbolicLink()) { + // unlink/re-link it + try { + yield ioUtil.lstat(destFile); + yield ioUtil.unlink(destFile); + } + catch (e) { + // Try to override file permission + if (e.code === 'EPERM') { + yield ioUtil.chmod(destFile, '0666'); + yield ioUtil.unlink(destFile); + } + // other errors = it doesn't exist, no work to do + } + // Copy over symlink + const symlinkFull = yield ioUtil.readlink(srcFile); + yield ioUtil.symlink(symlinkFull, destFile, ioUtil.IS_WINDOWS ? 'junction' : null); + } + else if (!(yield ioUtil.exists(destFile)) || force) { + yield ioUtil.copyFile(srcFile, destFile); + } + }); +} +//# sourceMappingURL=io.js.map + +/***/ }), + +/***/ 8248: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +/* @flow */ +/*:: + +type DotenvParseOptions = { + debug?: boolean +} + +// keys and values from src +type DotenvParseOutput = { [string]: string } + +type DotenvConfigOptions = { + path?: string, // path to .env file + encoding?: string, // encoding of .env file + debug?: string // turn on logging for debugging purposes +} + +type DotenvConfigOutput = { + parsed?: DotenvParseOutput, + error?: Error +} + +*/ + +const fs = __nccwpck_require__(7147) +const path = __nccwpck_require__(1017) + +function log (message /*: string */) { + console.log(`[dotenv][DEBUG] ${message}`) +} + +const NEWLINE = '\n' +const RE_INI_KEY_VAL = /^\s*([\w.-]+)\s*=\s*(.*)?\s*$/ +const RE_NEWLINES = /\\n/g +const NEWLINES_MATCH = /\n|\r|\r\n/ + +// Parses src into an Object +function parse (src /*: string | Buffer */, options /*: ?DotenvParseOptions */) /*: DotenvParseOutput */ { + const debug = Boolean(options && options.debug) + const obj = {} + + // convert Buffers before splitting into lines and processing + src.toString().split(NEWLINES_MATCH).forEach(function (line, idx) { + // matching "KEY' and 'VAL' in 'KEY=VAL' + const keyValueArr = line.match(RE_INI_KEY_VAL) + // matched? + if (keyValueArr != null) { + const key = keyValueArr[1] + // default undefined or missing values to empty string + let val = (keyValueArr[2] || '') + const end = val.length - 1 + const isDoubleQuoted = val[0] === '"' && val[end] === '"' + const isSingleQuoted = val[0] === "'" && val[end] === "'" + + // if single or double quoted, remove quotes + if (isSingleQuoted || isDoubleQuoted) { + val = val.substring(1, end) + + // if double quoted, expand newlines + if (isDoubleQuoted) { + val = val.replace(RE_NEWLINES, NEWLINE) + } + } else { + // remove surrounding whitespace + val = val.trim() + } + + obj[key] = val + } else if (debug) { + log(`did not match key and value when parsing line ${idx + 1}: ${line}`) + } + }) + + return obj +} + +// Populates process.env from .env file +function config (options /*: ?DotenvConfigOptions */) /*: DotenvConfigOutput */ { + let dotenvPath = path.resolve(process.cwd(), '.env') + let encoding /*: string */ = 'utf8' + let debug = false + + if (options) { + if (options.path != null) { + dotenvPath = options.path + } + if (options.encoding != null) { + encoding = options.encoding + } + if (options.debug != null) { + debug = true + } + } + + try { + // specifying an encoding returns a string instead of a buffer + const parsed = parse(fs.readFileSync(dotenvPath, { encoding }), { debug }) + + Object.keys(parsed).forEach(function (key) { + if (!Object.prototype.hasOwnProperty.call(process.env, key)) { + process.env[key] = parsed[key] + } else if (debug) { + log(`"${key}" is already defined in \`process.env\` and will not be overwritten`) + } + }) + + return { parsed } + } catch (e) { + return { error: e } + } +} + +module.exports.config = config +module.exports.parse = parse + + +/***/ }), + +/***/ 8672: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +module.exports = __nccwpck_require__(4983); + + +/***/ }), + +/***/ 4983: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +var net = __nccwpck_require__(1808); +var tls = __nccwpck_require__(4404); +var http = __nccwpck_require__(3685); +var https = __nccwpck_require__(5687); +var events = __nccwpck_require__(2361); +var assert = __nccwpck_require__(9491); +var util = __nccwpck_require__(3837); + + +exports.httpOverHttp = httpOverHttp; +exports.httpsOverHttp = httpsOverHttp; +exports.httpOverHttps = httpOverHttps; +exports.httpsOverHttps = httpsOverHttps; + + +function httpOverHttp(options) { + var agent = new TunnelingAgent(options); + agent.request = http.request; + return agent; +} + +function httpsOverHttp(options) { + var agent = new TunnelingAgent(options); + agent.request = http.request; + agent.createSocket = createSecureSocket; + agent.defaultPort = 443; + return agent; +} + +function httpOverHttps(options) { + var agent = new TunnelingAgent(options); + agent.request = https.request; + return agent; +} + +function httpsOverHttps(options) { + var agent = new TunnelingAgent(options); + agent.request = https.request; + agent.createSocket = createSecureSocket; + agent.defaultPort = 443; + return agent; +} + + +function TunnelingAgent(options) { + var self = this; + self.options = options || {}; + self.proxyOptions = self.options.proxy || {}; + self.maxSockets = self.options.maxSockets || http.Agent.defaultMaxSockets; + self.requests = []; + self.sockets = []; + + self.on('free', function onFree(socket, host, port, localAddress) { + var options = toOptions(host, port, localAddress); + for (var i = 0, len = self.requests.length; i < len; ++i) { + var pending = self.requests[i]; + if (pending.host === options.host && pending.port === options.port) { + // Detect the request to connect same origin server, + // reuse the connection. + self.requests.splice(i, 1); + pending.request.onSocket(socket); + return; + } + } + socket.destroy(); + self.removeSocket(socket); + }); +} +util.inherits(TunnelingAgent, events.EventEmitter); + +TunnelingAgent.prototype.addRequest = function addRequest(req, host, port, localAddress) { + var self = this; + var options = mergeOptions({request: req}, self.options, toOptions(host, port, localAddress)); + + if (self.sockets.length >= this.maxSockets) { + // We are over limit so we'll add it to the queue. + self.requests.push(options); + return; + } + + // If we are under maxSockets create a new one. + self.createSocket(options, function(socket) { + socket.on('free', onFree); + socket.on('close', onCloseOrRemove); + socket.on('agentRemove', onCloseOrRemove); + req.onSocket(socket); + + function onFree() { + self.emit('free', socket, options); + } + + function onCloseOrRemove(err) { + self.removeSocket(socket); + socket.removeListener('free', onFree); + socket.removeListener('close', onCloseOrRemove); + socket.removeListener('agentRemove', onCloseOrRemove); + } + }); +}; + +TunnelingAgent.prototype.createSocket = function createSocket(options, cb) { + var self = this; + var placeholder = {}; + self.sockets.push(placeholder); + + var connectOptions = mergeOptions({}, self.proxyOptions, { + method: 'CONNECT', + path: options.host + ':' + options.port, + agent: false, + headers: { + host: options.host + ':' + options.port + } + }); + if (options.localAddress) { + connectOptions.localAddress = options.localAddress; + } + if (connectOptions.proxyAuth) { + connectOptions.headers = connectOptions.headers || {}; + connectOptions.headers['Proxy-Authorization'] = 'Basic ' + + new Buffer(connectOptions.proxyAuth).toString('base64'); + } + + debug('making CONNECT request'); + var connectReq = self.request(connectOptions); + connectReq.useChunkedEncodingByDefault = false; // for v0.6 + connectReq.once('response', onResponse); // for v0.6 + connectReq.once('upgrade', onUpgrade); // for v0.6 + connectReq.once('connect', onConnect); // for v0.7 or later + connectReq.once('error', onError); + connectReq.end(); + + function onResponse(res) { + // Very hacky. This is necessary to avoid http-parser leaks. + res.upgrade = true; + } + + function onUpgrade(res, socket, head) { + // Hacky. + process.nextTick(function() { + onConnect(res, socket, head); + }); + } + + function onConnect(res, socket, head) { + connectReq.removeAllListeners(); + socket.removeAllListeners(); + + if (res.statusCode !== 200) { + debug('tunneling socket could not be established, statusCode=%d', + res.statusCode); + socket.destroy(); + var error = new Error('tunneling socket could not be established, ' + + 'statusCode=' + res.statusCode); + error.code = 'ECONNRESET'; + options.request.emit('error', error); + self.removeSocket(placeholder); + return; + } + if (head.length > 0) { + debug('got illegal response body from proxy'); + socket.destroy(); + var error = new Error('got illegal response body from proxy'); + error.code = 'ECONNRESET'; + options.request.emit('error', error); + self.removeSocket(placeholder); + return; + } + debug('tunneling connection has established'); + self.sockets[self.sockets.indexOf(placeholder)] = socket; + return cb(socket); + } + + function onError(cause) { + connectReq.removeAllListeners(); + + debug('tunneling socket could not be established, cause=%s\n', + cause.message, cause.stack); + var error = new Error('tunneling socket could not be established, ' + + 'cause=' + cause.message); + error.code = 'ECONNRESET'; + options.request.emit('error', error); + self.removeSocket(placeholder); + } +}; + +TunnelingAgent.prototype.removeSocket = function removeSocket(socket) { + var pos = this.sockets.indexOf(socket) + if (pos === -1) { + return; + } + this.sockets.splice(pos, 1); + + var pending = this.requests.shift(); + if (pending) { + // If we have pending requests and a socket gets closed a new one + // needs to be created to take over in the pool for the one that closed. + this.createSocket(pending, function(socket) { + pending.request.onSocket(socket); + }); + } +}; + +function createSecureSocket(options, cb) { + var self = this; + TunnelingAgent.prototype.createSocket.call(self, options, function(socket) { + var hostHeader = options.request.getHeader('host'); + var tlsOptions = mergeOptions({}, self.options, { + socket: socket, + servername: hostHeader ? hostHeader.replace(/:.*$/, '') : options.host + }); + + // 0 is dummy port for v0.6 + var secureSocket = tls.connect(0, tlsOptions); + self.sockets[self.sockets.indexOf(socket)] = secureSocket; + cb(secureSocket); + }); +} + + +function toOptions(host, port, localAddress) { + if (typeof host === 'string') { // since v0.10 + return { + host: host, + port: port, + localAddress: localAddress + }; + } + return host; // for v0.11 or later +} + +function mergeOptions(target) { + for (var i = 1, len = arguments.length; i < len; ++i) { + var overrides = arguments[i]; + if (typeof overrides === 'object') { + var keys = Object.keys(overrides); + for (var j = 0, keyLen = keys.length; j < keyLen; ++j) { + var k = keys[j]; + if (overrides[k] !== undefined) { + target[k] = overrides[k]; + } + } + } + } + return target; +} + + +var debug; +if (process.env.NODE_DEBUG && /\btunnel\b/.test(process.env.NODE_DEBUG)) { + debug = function() { + var args = Array.prototype.slice.call(arguments); + if (typeof args[0] === 'string') { + args[0] = 'TUNNEL: ' + args[0]; + } else { + args.unshift('TUNNEL:'); + } + console.error.apply(console, args); + } +} else { + debug = function() {}; +} +exports.debug = debug; // for test + + +/***/ }), + +/***/ 7364: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const Client = __nccwpck_require__(1180) +const Dispatcher = __nccwpck_require__(6504) +const errors = __nccwpck_require__(721) +const Pool = __nccwpck_require__(2395) +const BalancedPool = __nccwpck_require__(1562) +const Agent = __nccwpck_require__(8596) +const util = __nccwpck_require__(9522) +const { InvalidArgumentError } = errors +const api = __nccwpck_require__(3574) +const buildConnector = __nccwpck_require__(7530) +const MockClient = __nccwpck_require__(5846) +const MockAgent = __nccwpck_require__(6070) +const MockPool = __nccwpck_require__(5020) +const mockErrors = __nccwpck_require__(64) +const ProxyAgent = __nccwpck_require__(9391) +const RetryHandler = __nccwpck_require__(5764) +const { getGlobalDispatcher, setGlobalDispatcher } = __nccwpck_require__(5035) +const DecoratorHandler = __nccwpck_require__(194) +const RedirectHandler = __nccwpck_require__(7491) +const createRedirectInterceptor = __nccwpck_require__(5260) + +let hasCrypto +try { + __nccwpck_require__(6113) + hasCrypto = true +} catch { + hasCrypto = false +} + +Object.assign(Dispatcher.prototype, api) + +module.exports.Dispatcher = Dispatcher +module.exports.Client = Client +module.exports.Pool = Pool +module.exports.BalancedPool = BalancedPool +module.exports.Agent = Agent +module.exports.ProxyAgent = ProxyAgent +module.exports.RetryHandler = RetryHandler + +module.exports.DecoratorHandler = DecoratorHandler +module.exports.RedirectHandler = RedirectHandler +module.exports.createRedirectInterceptor = createRedirectInterceptor + +module.exports.buildConnector = buildConnector +module.exports.errors = errors + +function makeDispatcher (fn) { + return (url, opts, handler) => { + if (typeof opts === 'function') { + handler = opts + opts = null + } + + if (!url || (typeof url !== 'string' && typeof url !== 'object' && !(url instanceof URL))) { + throw new InvalidArgumentError('invalid url') + } + + if (opts != null && typeof opts !== 'object') { + throw new InvalidArgumentError('invalid opts') + } + + if (opts && opts.path != null) { + if (typeof opts.path !== 'string') { + throw new InvalidArgumentError('invalid opts.path') + } + + let path = opts.path + if (!opts.path.startsWith('/')) { + path = `/${path}` + } + + url = new URL(util.parseOrigin(url).origin + path) + } else { + if (!opts) { + opts = typeof url === 'object' ? url : {} + } + + url = util.parseURL(url) + } + + const { agent, dispatcher = getGlobalDispatcher() } = opts + + if (agent) { + throw new InvalidArgumentError('unsupported opts.agent. Did you mean opts.client?') + } + + return fn.call(dispatcher, { + ...opts, + origin: url.origin, + path: url.search ? `${url.pathname}${url.search}` : url.pathname, + method: opts.method || (opts.body ? 'PUT' : 'GET') + }, handler) + } +} + +module.exports.setGlobalDispatcher = setGlobalDispatcher +module.exports.getGlobalDispatcher = getGlobalDispatcher + +if (util.nodeMajor > 16 || (util.nodeMajor === 16 && util.nodeMinor >= 8)) { + let fetchImpl = null + module.exports.fetch = async function fetch (resource) { + if (!fetchImpl) { + fetchImpl = (__nccwpck_require__(5935).fetch) + } + + try { + return await fetchImpl(...arguments) + } catch (err) { + if (typeof err === 'object') { + Error.captureStackTrace(err, this) + } + + throw err + } + } + module.exports.Headers = __nccwpck_require__(7689).Headers + module.exports.Response = __nccwpck_require__(5796).Response + module.exports.Request = __nccwpck_require__(9157).Request + module.exports.FormData = __nccwpck_require__(968).FormData + module.exports.File = __nccwpck_require__(5479).File + module.exports.FileReader = __nccwpck_require__(9339).FileReader + + const { setGlobalOrigin, getGlobalOrigin } = __nccwpck_require__(5799) + + module.exports.setGlobalOrigin = setGlobalOrigin + module.exports.getGlobalOrigin = getGlobalOrigin + + const { CacheStorage } = __nccwpck_require__(2828) + const { kConstruct } = __nccwpck_require__(8812) + + // Cache & CacheStorage are tightly coupled with fetch. Even if it may run + // in an older version of Node, it doesn't have any use without fetch. + module.exports.caches = new CacheStorage(kConstruct) +} + +if (util.nodeMajor >= 16) { + const { deleteCookie, getCookies, getSetCookies, setCookie } = __nccwpck_require__(7484) + + module.exports.deleteCookie = deleteCookie + module.exports.getCookies = getCookies + module.exports.getSetCookies = getSetCookies + module.exports.setCookie = setCookie + + const { parseMIMEType, serializeAMimeType } = __nccwpck_require__(2791) + + module.exports.parseMIMEType = parseMIMEType + module.exports.serializeAMimeType = serializeAMimeType +} + +if (util.nodeMajor >= 18 && hasCrypto) { + const { WebSocket } = __nccwpck_require__(7936) + + module.exports.WebSocket = WebSocket +} + +module.exports.request = makeDispatcher(api.request) +module.exports.stream = makeDispatcher(api.stream) +module.exports.pipeline = makeDispatcher(api.pipeline) +module.exports.connect = makeDispatcher(api.connect) +module.exports.upgrade = makeDispatcher(api.upgrade) + +module.exports.MockClient = MockClient +module.exports.MockPool = MockPool +module.exports.MockAgent = MockAgent +module.exports.mockErrors = mockErrors + + +/***/ }), + +/***/ 8596: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { InvalidArgumentError } = __nccwpck_require__(721) +const { kClients, kRunning, kClose, kDestroy, kDispatch, kInterceptors } = __nccwpck_require__(9440) +const DispatcherBase = __nccwpck_require__(8462) +const Pool = __nccwpck_require__(2395) +const Client = __nccwpck_require__(1180) +const util = __nccwpck_require__(9522) +const createRedirectInterceptor = __nccwpck_require__(5260) +const { WeakRef, FinalizationRegistry } = __nccwpck_require__(231)() + +const kOnConnect = Symbol('onConnect') +const kOnDisconnect = Symbol('onDisconnect') +const kOnConnectionError = Symbol('onConnectionError') +const kMaxRedirections = Symbol('maxRedirections') +const kOnDrain = Symbol('onDrain') +const kFactory = Symbol('factory') +const kFinalizer = Symbol('finalizer') +const kOptions = Symbol('options') + +function defaultFactory (origin, opts) { + return opts && opts.connections === 1 + ? new Client(origin, opts) + : new Pool(origin, opts) +} + +class Agent extends DispatcherBase { + constructor ({ factory = defaultFactory, maxRedirections = 0, connect, ...options } = {}) { + super() + + if (typeof factory !== 'function') { + throw new InvalidArgumentError('factory must be a function.') + } + + if (connect != null && typeof connect !== 'function' && typeof connect !== 'object') { + throw new InvalidArgumentError('connect must be a function or an object') + } + + if (!Number.isInteger(maxRedirections) || maxRedirections < 0) { + throw new InvalidArgumentError('maxRedirections must be a positive number') + } + + if (connect && typeof connect !== 'function') { + connect = { ...connect } + } + + this[kInterceptors] = options.interceptors && options.interceptors.Agent && Array.isArray(options.interceptors.Agent) + ? options.interceptors.Agent + : [createRedirectInterceptor({ maxRedirections })] + + this[kOptions] = { ...util.deepClone(options), connect } + this[kOptions].interceptors = options.interceptors + ? { ...options.interceptors } + : undefined + this[kMaxRedirections] = maxRedirections + this[kFactory] = factory + this[kClients] = new Map() + this[kFinalizer] = new FinalizationRegistry(/* istanbul ignore next: gc is undeterministic */ key => { + const ref = this[kClients].get(key) + if (ref !== undefined && ref.deref() === undefined) { + this[kClients].delete(key) + } + }) + + const agent = this + + this[kOnDrain] = (origin, targets) => { + agent.emit('drain', origin, [agent, ...targets]) + } + + this[kOnConnect] = (origin, targets) => { + agent.emit('connect', origin, [agent, ...targets]) + } + + this[kOnDisconnect] = (origin, targets, err) => { + agent.emit('disconnect', origin, [agent, ...targets], err) + } + + this[kOnConnectionError] = (origin, targets, err) => { + agent.emit('connectionError', origin, [agent, ...targets], err) + } + } + + get [kRunning] () { + let ret = 0 + for (const ref of this[kClients].values()) { + const client = ref.deref() + /* istanbul ignore next: gc is undeterministic */ + if (client) { + ret += client[kRunning] + } + } + return ret + } + + [kDispatch] (opts, handler) { + let key + if (opts.origin && (typeof opts.origin === 'string' || opts.origin instanceof URL)) { + key = String(opts.origin) + } else { + throw new InvalidArgumentError('opts.origin must be a non-empty string or URL.') + } + + const ref = this[kClients].get(key) + + let dispatcher = ref ? ref.deref() : null + if (!dispatcher) { + dispatcher = this[kFactory](opts.origin, this[kOptions]) + .on('drain', this[kOnDrain]) + .on('connect', this[kOnConnect]) + .on('disconnect', this[kOnDisconnect]) + .on('connectionError', this[kOnConnectionError]) + + this[kClients].set(key, new WeakRef(dispatcher)) + this[kFinalizer].register(dispatcher, key) + } + + return dispatcher.dispatch(opts, handler) + } + + async [kClose] () { + const closePromises = [] + for (const ref of this[kClients].values()) { + const client = ref.deref() + /* istanbul ignore else: gc is undeterministic */ + if (client) { + closePromises.push(client.close()) + } + } + + await Promise.all(closePromises) + } + + async [kDestroy] (err) { + const destroyPromises = [] + for (const ref of this[kClients].values()) { + const client = ref.deref() + /* istanbul ignore else: gc is undeterministic */ + if (client) { + destroyPromises.push(client.destroy(err)) + } + } + + await Promise.all(destroyPromises) + } +} + +module.exports = Agent + + +/***/ }), + +/***/ 95: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +const { addAbortListener } = __nccwpck_require__(9522) +const { RequestAbortedError } = __nccwpck_require__(721) + +const kListener = Symbol('kListener') +const kSignal = Symbol('kSignal') + +function abort (self) { + if (self.abort) { + self.abort() + } else { + self.onError(new RequestAbortedError()) + } +} + +function addSignal (self, signal) { + self[kSignal] = null + self[kListener] = null + + if (!signal) { + return + } + + if (signal.aborted) { + abort(self) + return + } + + self[kSignal] = signal + self[kListener] = () => { + abort(self) + } + + addAbortListener(self[kSignal], self[kListener]) +} + +function removeSignal (self) { + if (!self[kSignal]) { + return + } + + if ('removeEventListener' in self[kSignal]) { + self[kSignal].removeEventListener('abort', self[kListener]) + } else { + self[kSignal].removeListener('abort', self[kListener]) + } + + self[kSignal] = null + self[kListener] = null +} + +module.exports = { + addSignal, + removeSignal +} + + +/***/ }), + +/***/ 8588: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { AsyncResource } = __nccwpck_require__(852) +const { InvalidArgumentError, RequestAbortedError, SocketError } = __nccwpck_require__(721) +const util = __nccwpck_require__(9522) +const { addSignal, removeSignal } = __nccwpck_require__(95) + +class ConnectHandler extends AsyncResource { + constructor (opts, callback) { + if (!opts || typeof opts !== 'object') { + throw new InvalidArgumentError('invalid opts') + } + + if (typeof callback !== 'function') { + throw new InvalidArgumentError('invalid callback') + } + + const { signal, opaque, responseHeaders } = opts + + if (signal && typeof signal.on !== 'function' && typeof signal.addEventListener !== 'function') { + throw new InvalidArgumentError('signal must be an EventEmitter or EventTarget') + } + + super('UNDICI_CONNECT') + + this.opaque = opaque || null + this.responseHeaders = responseHeaders || null + this.callback = callback + this.abort = null + + addSignal(this, signal) + } + + onConnect (abort, context) { + if (!this.callback) { + throw new RequestAbortedError() + } + + this.abort = abort + this.context = context + } + + onHeaders () { + throw new SocketError('bad connect', null) + } + + onUpgrade (statusCode, rawHeaders, socket) { + const { callback, opaque, context } = this + + removeSignal(this) + + this.callback = null + + let headers = rawHeaders + // Indicates is an HTTP2Session + if (headers != null) { + headers = this.responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) + } + + this.runInAsyncScope(callback, null, null, { + statusCode, + headers, + socket, + opaque, + context + }) + } + + onError (err) { + const { callback, opaque } = this + + removeSignal(this) + + if (callback) { + this.callback = null + queueMicrotask(() => { + this.runInAsyncScope(callback, null, err, { opaque }) + }) + } + } +} + +function connect (opts, callback) { + if (callback === undefined) { + return new Promise((resolve, reject) => { + connect.call(this, opts, (err, data) => { + return err ? reject(err) : resolve(data) + }) + }) + } + + try { + const connectHandler = new ConnectHandler(opts, callback) + this.dispatch({ ...opts, method: 'CONNECT' }, connectHandler) + } catch (err) { + if (typeof callback !== 'function') { + throw err + } + const opaque = opts && opts.opaque + queueMicrotask(() => callback(err, { opaque })) + } +} + +module.exports = connect + + +/***/ }), + +/***/ 1705: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { + Readable, + Duplex, + PassThrough +} = __nccwpck_require__(2781) +const { + InvalidArgumentError, + InvalidReturnValueError, + RequestAbortedError +} = __nccwpck_require__(721) +const util = __nccwpck_require__(9522) +const { AsyncResource } = __nccwpck_require__(852) +const { addSignal, removeSignal } = __nccwpck_require__(95) +const assert = __nccwpck_require__(9491) + +const kResume = Symbol('resume') + +class PipelineRequest extends Readable { + constructor () { + super({ autoDestroy: true }) + + this[kResume] = null + } + + _read () { + const { [kResume]: resume } = this + + if (resume) { + this[kResume] = null + resume() + } + } + + _destroy (err, callback) { + this._read() + + callback(err) + } +} + +class PipelineResponse extends Readable { + constructor (resume) { + super({ autoDestroy: true }) + this[kResume] = resume + } + + _read () { + this[kResume]() + } + + _destroy (err, callback) { + if (!err && !this._readableState.endEmitted) { + err = new RequestAbortedError() + } + + callback(err) + } +} + +class PipelineHandler extends AsyncResource { + constructor (opts, handler) { + if (!opts || typeof opts !== 'object') { + throw new InvalidArgumentError('invalid opts') + } + + if (typeof handler !== 'function') { + throw new InvalidArgumentError('invalid handler') + } + + const { signal, method, opaque, onInfo, responseHeaders } = opts + + if (signal && typeof signal.on !== 'function' && typeof signal.addEventListener !== 'function') { + throw new InvalidArgumentError('signal must be an EventEmitter or EventTarget') + } + + if (method === 'CONNECT') { + throw new InvalidArgumentError('invalid method') + } + + if (onInfo && typeof onInfo !== 'function') { + throw new InvalidArgumentError('invalid onInfo callback') + } + + super('UNDICI_PIPELINE') + + this.opaque = opaque || null + this.responseHeaders = responseHeaders || null + this.handler = handler + this.abort = null + this.context = null + this.onInfo = onInfo || null + + this.req = new PipelineRequest().on('error', util.nop) + + this.ret = new Duplex({ + readableObjectMode: opts.objectMode, + autoDestroy: true, + read: () => { + const { body } = this + + if (body && body.resume) { + body.resume() + } + }, + write: (chunk, encoding, callback) => { + const { req } = this + + if (req.push(chunk, encoding) || req._readableState.destroyed) { + callback() + } else { + req[kResume] = callback + } + }, + destroy: (err, callback) => { + const { body, req, res, ret, abort } = this + + if (!err && !ret._readableState.endEmitted) { + err = new RequestAbortedError() + } + + if (abort && err) { + abort() + } + + util.destroy(body, err) + util.destroy(req, err) + util.destroy(res, err) + + removeSignal(this) + + callback(err) + } + }).on('prefinish', () => { + const { req } = this + + // Node < 15 does not call _final in same tick. + req.push(null) + }) + + this.res = null + + addSignal(this, signal) + } + + onConnect (abort, context) { + const { ret, res } = this + + assert(!res, 'pipeline cannot be retried') + + if (ret.destroyed) { + throw new RequestAbortedError() + } + + this.abort = abort + this.context = context + } + + onHeaders (statusCode, rawHeaders, resume) { + const { opaque, handler, context } = this + + if (statusCode < 200) { + if (this.onInfo) { + const headers = this.responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) + this.onInfo({ statusCode, headers }) + } + return + } + + this.res = new PipelineResponse(resume) + + let body + try { + this.handler = null + const headers = this.responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) + body = this.runInAsyncScope(handler, null, { + statusCode, + headers, + opaque, + body: this.res, + context + }) + } catch (err) { + this.res.on('error', util.nop) + throw err + } + + if (!body || typeof body.on !== 'function') { + throw new InvalidReturnValueError('expected Readable') + } + + body + .on('data', (chunk) => { + const { ret, body } = this + + if (!ret.push(chunk) && body.pause) { + body.pause() + } + }) + .on('error', (err) => { + const { ret } = this + + util.destroy(ret, err) + }) + .on('end', () => { + const { ret } = this + + ret.push(null) + }) + .on('close', () => { + const { ret } = this + + if (!ret._readableState.ended) { + util.destroy(ret, new RequestAbortedError()) + } + }) + + this.body = body + } + + onData (chunk) { + const { res } = this + return res.push(chunk) + } + + onComplete (trailers) { + const { res } = this + res.push(null) + } + + onError (err) { + const { ret } = this + this.handler = null + util.destroy(ret, err) + } +} + +function pipeline (opts, handler) { + try { + const pipelineHandler = new PipelineHandler(opts, handler) + this.dispatch({ ...opts, body: pipelineHandler.req }, pipelineHandler) + return pipelineHandler.ret + } catch (err) { + return new PassThrough().destroy(err) + } +} + +module.exports = pipeline + + +/***/ }), + +/***/ 4825: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const Readable = __nccwpck_require__(3079) +const { + InvalidArgumentError, + RequestAbortedError +} = __nccwpck_require__(721) +const util = __nccwpck_require__(9522) +const { getResolveErrorBodyCallback } = __nccwpck_require__(7392) +const { AsyncResource } = __nccwpck_require__(852) +const { addSignal, removeSignal } = __nccwpck_require__(95) + +class RequestHandler extends AsyncResource { + constructor (opts, callback) { + if (!opts || typeof opts !== 'object') { + throw new InvalidArgumentError('invalid opts') + } + + const { signal, method, opaque, body, onInfo, responseHeaders, throwOnError, highWaterMark } = opts + + try { + if (typeof callback !== 'function') { + throw new InvalidArgumentError('invalid callback') + } + + if (highWaterMark && (typeof highWaterMark !== 'number' || highWaterMark < 0)) { + throw new InvalidArgumentError('invalid highWaterMark') + } + + if (signal && typeof signal.on !== 'function' && typeof signal.addEventListener !== 'function') { + throw new InvalidArgumentError('signal must be an EventEmitter or EventTarget') + } + + if (method === 'CONNECT') { + throw new InvalidArgumentError('invalid method') + } + + if (onInfo && typeof onInfo !== 'function') { + throw new InvalidArgumentError('invalid onInfo callback') + } + + super('UNDICI_REQUEST') + } catch (err) { + if (util.isStream(body)) { + util.destroy(body.on('error', util.nop), err) + } + throw err + } + + this.responseHeaders = responseHeaders || null + this.opaque = opaque || null + this.callback = callback + this.res = null + this.abort = null + this.body = body + this.trailers = {} + this.context = null + this.onInfo = onInfo || null + this.throwOnError = throwOnError + this.highWaterMark = highWaterMark + + if (util.isStream(body)) { + body.on('error', (err) => { + this.onError(err) + }) + } + + addSignal(this, signal) + } + + onConnect (abort, context) { + if (!this.callback) { + throw new RequestAbortedError() + } + + this.abort = abort + this.context = context + } + + onHeaders (statusCode, rawHeaders, resume, statusMessage) { + const { callback, opaque, abort, context, responseHeaders, highWaterMark } = this + + const headers = responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) + + if (statusCode < 200) { + if (this.onInfo) { + this.onInfo({ statusCode, headers }) + } + return + } + + const parsedHeaders = responseHeaders === 'raw' ? util.parseHeaders(rawHeaders) : headers + const contentType = parsedHeaders['content-type'] + const body = new Readable({ resume, abort, contentType, highWaterMark }) + + this.callback = null + this.res = body + if (callback !== null) { + if (this.throwOnError && statusCode >= 400) { + this.runInAsyncScope(getResolveErrorBodyCallback, null, + { callback, body, contentType, statusCode, statusMessage, headers } + ) + } else { + this.runInAsyncScope(callback, null, null, { + statusCode, + headers, + trailers: this.trailers, + opaque, + body, + context + }) + } + } + } + + onData (chunk) { + const { res } = this + return res.push(chunk) + } + + onComplete (trailers) { + const { res } = this + + removeSignal(this) + + util.parseHeaders(trailers, this.trailers) + + res.push(null) + } + + onError (err) { + const { res, callback, body, opaque } = this + + removeSignal(this) + + if (callback) { + // TODO: Does this need queueMicrotask? + this.callback = null + queueMicrotask(() => { + this.runInAsyncScope(callback, null, err, { opaque }) + }) + } + + if (res) { + this.res = null + // Ensure all queued handlers are invoked before destroying res. + queueMicrotask(() => { + util.destroy(res, err) + }) + } + + if (body) { + this.body = null + util.destroy(body, err) + } + } +} + +function request (opts, callback) { + if (callback === undefined) { + return new Promise((resolve, reject) => { + request.call(this, opts, (err, data) => { + return err ? reject(err) : resolve(data) + }) + }) + } + + try { + this.dispatch(opts, new RequestHandler(opts, callback)) + } catch (err) { + if (typeof callback !== 'function') { + throw err + } + const opaque = opts && opts.opaque + queueMicrotask(() => callback(err, { opaque })) + } +} + +module.exports = request + + +/***/ }), + +/***/ 5445: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { finished, PassThrough } = __nccwpck_require__(2781) +const { + InvalidArgumentError, + InvalidReturnValueError, + RequestAbortedError +} = __nccwpck_require__(721) +const util = __nccwpck_require__(9522) +const { getResolveErrorBodyCallback } = __nccwpck_require__(7392) +const { AsyncResource } = __nccwpck_require__(852) +const { addSignal, removeSignal } = __nccwpck_require__(95) + +class StreamHandler extends AsyncResource { + constructor (opts, factory, callback) { + if (!opts || typeof opts !== 'object') { + throw new InvalidArgumentError('invalid opts') + } + + const { signal, method, opaque, body, onInfo, responseHeaders, throwOnError } = opts + + try { + if (typeof callback !== 'function') { + throw new InvalidArgumentError('invalid callback') + } + + if (typeof factory !== 'function') { + throw new InvalidArgumentError('invalid factory') + } + + if (signal && typeof signal.on !== 'function' && typeof signal.addEventListener !== 'function') { + throw new InvalidArgumentError('signal must be an EventEmitter or EventTarget') + } + + if (method === 'CONNECT') { + throw new InvalidArgumentError('invalid method') + } + + if (onInfo && typeof onInfo !== 'function') { + throw new InvalidArgumentError('invalid onInfo callback') + } + + super('UNDICI_STREAM') + } catch (err) { + if (util.isStream(body)) { + util.destroy(body.on('error', util.nop), err) + } + throw err + } + + this.responseHeaders = responseHeaders || null + this.opaque = opaque || null + this.factory = factory + this.callback = callback + this.res = null + this.abort = null + this.context = null + this.trailers = null + this.body = body + this.onInfo = onInfo || null + this.throwOnError = throwOnError || false + + if (util.isStream(body)) { + body.on('error', (err) => { + this.onError(err) + }) + } + + addSignal(this, signal) + } + + onConnect (abort, context) { + if (!this.callback) { + throw new RequestAbortedError() + } + + this.abort = abort + this.context = context + } + + onHeaders (statusCode, rawHeaders, resume, statusMessage) { + const { factory, opaque, context, callback, responseHeaders } = this + + const headers = responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) + + if (statusCode < 200) { + if (this.onInfo) { + this.onInfo({ statusCode, headers }) + } + return + } + + this.factory = null + + let res + + if (this.throwOnError && statusCode >= 400) { + const parsedHeaders = responseHeaders === 'raw' ? util.parseHeaders(rawHeaders) : headers + const contentType = parsedHeaders['content-type'] + res = new PassThrough() + + this.callback = null + this.runInAsyncScope(getResolveErrorBodyCallback, null, + { callback, body: res, contentType, statusCode, statusMessage, headers } + ) + } else { + if (factory === null) { + return + } + + res = this.runInAsyncScope(factory, null, { + statusCode, + headers, + opaque, + context + }) + + if ( + !res || + typeof res.write !== 'function' || + typeof res.end !== 'function' || + typeof res.on !== 'function' + ) { + throw new InvalidReturnValueError('expected Writable') + } + + // TODO: Avoid finished. It registers an unnecessary amount of listeners. + finished(res, { readable: false }, (err) => { + const { callback, res, opaque, trailers, abort } = this + + this.res = null + if (err || !res.readable) { + util.destroy(res, err) + } + + this.callback = null + this.runInAsyncScope(callback, null, err || null, { opaque, trailers }) + + if (err) { + abort() + } + }) + } + + res.on('drain', resume) + + this.res = res + + const needDrain = res.writableNeedDrain !== undefined + ? res.writableNeedDrain + : res._writableState && res._writableState.needDrain + + return needDrain !== true + } + + onData (chunk) { + const { res } = this + + return res ? res.write(chunk) : true + } + + onComplete (trailers) { + const { res } = this + + removeSignal(this) + + if (!res) { + return + } + + this.trailers = util.parseHeaders(trailers) + + res.end() + } + + onError (err) { + const { res, callback, opaque, body } = this + + removeSignal(this) + + this.factory = null + + if (res) { + this.res = null + util.destroy(res, err) + } else if (callback) { + this.callback = null + queueMicrotask(() => { + this.runInAsyncScope(callback, null, err, { opaque }) + }) + } + + if (body) { + this.body = null + util.destroy(body, err) + } + } +} + +function stream (opts, factory, callback) { + if (callback === undefined) { + return new Promise((resolve, reject) => { + stream.call(this, opts, factory, (err, data) => { + return err ? reject(err) : resolve(data) + }) + }) + } + + try { + this.dispatch(opts, new StreamHandler(opts, factory, callback)) + } catch (err) { + if (typeof callback !== 'function') { + throw err + } + const opaque = opts && opts.opaque + queueMicrotask(() => callback(err, { opaque })) + } +} + +module.exports = stream + + +/***/ }), + +/***/ 7282: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { InvalidArgumentError, RequestAbortedError, SocketError } = __nccwpck_require__(721) +const { AsyncResource } = __nccwpck_require__(852) +const util = __nccwpck_require__(9522) +const { addSignal, removeSignal } = __nccwpck_require__(95) +const assert = __nccwpck_require__(9491) + +class UpgradeHandler extends AsyncResource { + constructor (opts, callback) { + if (!opts || typeof opts !== 'object') { + throw new InvalidArgumentError('invalid opts') + } + + if (typeof callback !== 'function') { + throw new InvalidArgumentError('invalid callback') + } + + const { signal, opaque, responseHeaders } = opts + + if (signal && typeof signal.on !== 'function' && typeof signal.addEventListener !== 'function') { + throw new InvalidArgumentError('signal must be an EventEmitter or EventTarget') + } + + super('UNDICI_UPGRADE') + + this.responseHeaders = responseHeaders || null + this.opaque = opaque || null + this.callback = callback + this.abort = null + this.context = null + + addSignal(this, signal) + } + + onConnect (abort, context) { + if (!this.callback) { + throw new RequestAbortedError() + } + + this.abort = abort + this.context = null + } + + onHeaders () { + throw new SocketError('bad upgrade', null) + } + + onUpgrade (statusCode, rawHeaders, socket) { + const { callback, opaque, context } = this + + assert.strictEqual(statusCode, 101) + + removeSignal(this) + + this.callback = null + const headers = this.responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) + this.runInAsyncScope(callback, null, null, { + headers, + socket, + opaque, + context + }) + } + + onError (err) { + const { callback, opaque } = this + + removeSignal(this) + + if (callback) { + this.callback = null + queueMicrotask(() => { + this.runInAsyncScope(callback, null, err, { opaque }) + }) + } + } +} + +function upgrade (opts, callback) { + if (callback === undefined) { + return new Promise((resolve, reject) => { + upgrade.call(this, opts, (err, data) => { + return err ? reject(err) : resolve(data) + }) + }) + } + + try { + const upgradeHandler = new UpgradeHandler(opts, callback) + this.dispatch({ + ...opts, + method: opts.method || 'GET', + upgrade: opts.protocol || 'Websocket' + }, upgradeHandler) + } catch (err) { + if (typeof callback !== 'function') { + throw err + } + const opaque = opts && opts.opaque + queueMicrotask(() => callback(err, { opaque })) + } +} + +module.exports = upgrade + + +/***/ }), + +/***/ 3574: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +module.exports.request = __nccwpck_require__(4825) +module.exports.stream = __nccwpck_require__(5445) +module.exports.pipeline = __nccwpck_require__(1705) +module.exports.upgrade = __nccwpck_require__(7282) +module.exports.connect = __nccwpck_require__(8588) + + +/***/ }), + +/***/ 3079: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; +// Ported from https://github.com/nodejs/undici/pull/907 + + + +const assert = __nccwpck_require__(9491) +const { Readable } = __nccwpck_require__(2781) +const { RequestAbortedError, NotSupportedError, InvalidArgumentError } = __nccwpck_require__(721) +const util = __nccwpck_require__(9522) +const { ReadableStreamFrom, toUSVString } = __nccwpck_require__(9522) + +let Blob + +const kConsume = Symbol('kConsume') +const kReading = Symbol('kReading') +const kBody = Symbol('kBody') +const kAbort = Symbol('abort') +const kContentType = Symbol('kContentType') + +const noop = () => {} + +module.exports = class BodyReadable extends Readable { + constructor ({ + resume, + abort, + contentType = '', + highWaterMark = 64 * 1024 // Same as nodejs fs streams. + }) { + super({ + autoDestroy: true, + read: resume, + highWaterMark + }) + + this._readableState.dataEmitted = false + + this[kAbort] = abort + this[kConsume] = null + this[kBody] = null + this[kContentType] = contentType + + // Is stream being consumed through Readable API? + // This is an optimization so that we avoid checking + // for 'data' and 'readable' listeners in the hot path + // inside push(). + this[kReading] = false + } + + destroy (err) { + if (this.destroyed) { + // Node < 16 + return this + } + + if (!err && !this._readableState.endEmitted) { + err = new RequestAbortedError() + } + + if (err) { + this[kAbort]() + } + + return super.destroy(err) + } + + emit (ev, ...args) { + if (ev === 'data') { + // Node < 16.7 + this._readableState.dataEmitted = true + } else if (ev === 'error') { + // Node < 16 + this._readableState.errorEmitted = true + } + return super.emit(ev, ...args) + } + + on (ev, ...args) { + if (ev === 'data' || ev === 'readable') { + this[kReading] = true + } + return super.on(ev, ...args) + } + + addListener (ev, ...args) { + return this.on(ev, ...args) + } + + off (ev, ...args) { + const ret = super.off(ev, ...args) + if (ev === 'data' || ev === 'readable') { + this[kReading] = ( + this.listenerCount('data') > 0 || + this.listenerCount('readable') > 0 + ) + } + return ret + } + + removeListener (ev, ...args) { + return this.off(ev, ...args) + } + + push (chunk) { + if (this[kConsume] && chunk !== null && this.readableLength === 0) { + consumePush(this[kConsume], chunk) + return this[kReading] ? super.push(chunk) : true + } + return super.push(chunk) + } + + // https://fetch.spec.whatwg.org/#dom-body-text + async text () { + return consume(this, 'text') + } + + // https://fetch.spec.whatwg.org/#dom-body-json + async json () { + return consume(this, 'json') + } + + // https://fetch.spec.whatwg.org/#dom-body-blob + async blob () { + return consume(this, 'blob') + } + + // https://fetch.spec.whatwg.org/#dom-body-arraybuffer + async arrayBuffer () { + return consume(this, 'arrayBuffer') + } + + // https://fetch.spec.whatwg.org/#dom-body-formdata + async formData () { + // TODO: Implement. + throw new NotSupportedError() + } + + // https://fetch.spec.whatwg.org/#dom-body-bodyused + get bodyUsed () { + return util.isDisturbed(this) + } + + // https://fetch.spec.whatwg.org/#dom-body-body + get body () { + if (!this[kBody]) { + this[kBody] = ReadableStreamFrom(this) + if (this[kConsume]) { + // TODO: Is this the best way to force a lock? + this[kBody].getReader() // Ensure stream is locked. + assert(this[kBody].locked) + } + } + return this[kBody] + } + + dump (opts) { + let limit = opts && Number.isFinite(opts.limit) ? opts.limit : 262144 + const signal = opts && opts.signal + + if (signal) { + try { + if (typeof signal !== 'object' || !('aborted' in signal)) { + throw new InvalidArgumentError('signal must be an AbortSignal') + } + util.throwIfAborted(signal) + } catch (err) { + return Promise.reject(err) + } + } + + if (this.closed) { + return Promise.resolve(null) + } + + return new Promise((resolve, reject) => { + const signalListenerCleanup = signal + ? util.addAbortListener(signal, () => { + this.destroy() + }) + : noop + + this + .on('close', function () { + signalListenerCleanup() + if (signal?.aborted) { + reject(signal.reason || Object.assign(new Error('The operation was aborted'), { name: 'AbortError' })) + } else { + resolve(null) + } + }) + .on('error', noop) + .on('data', function (chunk) { + limit -= chunk.length + if (limit <= 0) { + this.destroy() + } + }) + .resume() + }) + } +} + +// https://streams.spec.whatwg.org/#readablestream-locked +function isLocked (self) { + // Consume is an implicit lock. + return (self[kBody] && self[kBody].locked === true) || self[kConsume] +} + +// https://fetch.spec.whatwg.org/#body-unusable +function isUnusable (self) { + return util.isDisturbed(self) || isLocked(self) +} + +async function consume (stream, type) { + if (isUnusable(stream)) { + throw new TypeError('unusable') + } + + assert(!stream[kConsume]) + + return new Promise((resolve, reject) => { + stream[kConsume] = { + type, + stream, + resolve, + reject, + length: 0, + body: [] + } + + stream + .on('error', function (err) { + consumeFinish(this[kConsume], err) + }) + .on('close', function () { + if (this[kConsume].body !== null) { + consumeFinish(this[kConsume], new RequestAbortedError()) + } + }) + + process.nextTick(consumeStart, stream[kConsume]) + }) +} + +function consumeStart (consume) { + if (consume.body === null) { + return + } + + const { _readableState: state } = consume.stream + + for (const chunk of state.buffer) { + consumePush(consume, chunk) + } + + if (state.endEmitted) { + consumeEnd(this[kConsume]) + } else { + consume.stream.on('end', function () { + consumeEnd(this[kConsume]) + }) + } + + consume.stream.resume() + + while (consume.stream.read() != null) { + // Loop + } +} + +function consumeEnd (consume) { + const { type, body, resolve, stream, length } = consume + + try { + if (type === 'text') { + resolve(toUSVString(Buffer.concat(body))) + } else if (type === 'json') { + resolve(JSON.parse(Buffer.concat(body))) + } else if (type === 'arrayBuffer') { + const dst = new Uint8Array(length) + + let pos = 0 + for (const buf of body) { + dst.set(buf, pos) + pos += buf.byteLength + } + + resolve(dst.buffer) + } else if (type === 'blob') { + if (!Blob) { + Blob = (__nccwpck_require__(4300).Blob) + } + resolve(new Blob(body, { type: stream[kContentType] })) + } + + consumeFinish(consume) + } catch (err) { + stream.destroy(err) + } +} + +function consumePush (consume, chunk) { + consume.length += chunk.length + consume.body.push(chunk) +} + +function consumeFinish (consume, err) { + if (consume.body === null) { + return + } + + if (err) { + consume.reject(err) + } else { + consume.resolve() + } + + consume.type = null + consume.stream = null + consume.resolve = null + consume.reject = null + consume.length = 0 + consume.body = null +} + + +/***/ }), + +/***/ 7392: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +const assert = __nccwpck_require__(9491) +const { + ResponseStatusCodeError +} = __nccwpck_require__(721) +const { toUSVString } = __nccwpck_require__(9522) + +async function getResolveErrorBodyCallback ({ callback, body, contentType, statusCode, statusMessage, headers }) { + assert(body) + + let chunks = [] + let limit = 0 + + for await (const chunk of body) { + chunks.push(chunk) + limit += chunk.length + if (limit > 128 * 1024) { + chunks = null + break + } + } + + if (statusCode === 204 || !contentType || !chunks) { + process.nextTick(callback, new ResponseStatusCodeError(`Response status code ${statusCode}${statusMessage ? `: ${statusMessage}` : ''}`, statusCode, headers)) + return + } + + try { + if (contentType.startsWith('application/json')) { + const payload = JSON.parse(toUSVString(Buffer.concat(chunks))) + process.nextTick(callback, new ResponseStatusCodeError(`Response status code ${statusCode}${statusMessage ? `: ${statusMessage}` : ''}`, statusCode, headers, payload)) + return + } + + if (contentType.startsWith('text/')) { + const payload = toUSVString(Buffer.concat(chunks)) + process.nextTick(callback, new ResponseStatusCodeError(`Response status code ${statusCode}${statusMessage ? `: ${statusMessage}` : ''}`, statusCode, headers, payload)) + return + } + } catch (err) { + // Process in a fallback if error + } + + process.nextTick(callback, new ResponseStatusCodeError(`Response status code ${statusCode}${statusMessage ? `: ${statusMessage}` : ''}`, statusCode, headers)) +} + +module.exports = { getResolveErrorBodyCallback } + + +/***/ }), + +/***/ 1562: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { + BalancedPoolMissingUpstreamError, + InvalidArgumentError +} = __nccwpck_require__(721) +const { + PoolBase, + kClients, + kNeedDrain, + kAddClient, + kRemoveClient, + kGetDispatcher +} = __nccwpck_require__(8617) +const Pool = __nccwpck_require__(2395) +const { kUrl, kInterceptors } = __nccwpck_require__(9440) +const { parseOrigin } = __nccwpck_require__(9522) +const kFactory = Symbol('factory') + +const kOptions = Symbol('options') +const kGreatestCommonDivisor = Symbol('kGreatestCommonDivisor') +const kCurrentWeight = Symbol('kCurrentWeight') +const kIndex = Symbol('kIndex') +const kWeight = Symbol('kWeight') +const kMaxWeightPerServer = Symbol('kMaxWeightPerServer') +const kErrorPenalty = Symbol('kErrorPenalty') + +function getGreatestCommonDivisor (a, b) { + if (b === 0) return a + return getGreatestCommonDivisor(b, a % b) +} + +function defaultFactory (origin, opts) { + return new Pool(origin, opts) +} + +class BalancedPool extends PoolBase { + constructor (upstreams = [], { factory = defaultFactory, ...opts } = {}) { + super() + + this[kOptions] = opts + this[kIndex] = -1 + this[kCurrentWeight] = 0 + + this[kMaxWeightPerServer] = this[kOptions].maxWeightPerServer || 100 + this[kErrorPenalty] = this[kOptions].errorPenalty || 15 + + if (!Array.isArray(upstreams)) { + upstreams = [upstreams] + } + + if (typeof factory !== 'function') { + throw new InvalidArgumentError('factory must be a function.') + } + + this[kInterceptors] = opts.interceptors && opts.interceptors.BalancedPool && Array.isArray(opts.interceptors.BalancedPool) + ? opts.interceptors.BalancedPool + : [] + this[kFactory] = factory + + for (const upstream of upstreams) { + this.addUpstream(upstream) + } + this._updateBalancedPoolStats() + } + + addUpstream (upstream) { + const upstreamOrigin = parseOrigin(upstream).origin + + if (this[kClients].find((pool) => ( + pool[kUrl].origin === upstreamOrigin && + pool.closed !== true && + pool.destroyed !== true + ))) { + return this + } + const pool = this[kFactory](upstreamOrigin, Object.assign({}, this[kOptions])) + + this[kAddClient](pool) + pool.on('connect', () => { + pool[kWeight] = Math.min(this[kMaxWeightPerServer], pool[kWeight] + this[kErrorPenalty]) + }) + + pool.on('connectionError', () => { + pool[kWeight] = Math.max(1, pool[kWeight] - this[kErrorPenalty]) + this._updateBalancedPoolStats() + }) + + pool.on('disconnect', (...args) => { + const err = args[2] + if (err && err.code === 'UND_ERR_SOCKET') { + // decrease the weight of the pool. + pool[kWeight] = Math.max(1, pool[kWeight] - this[kErrorPenalty]) + this._updateBalancedPoolStats() + } + }) + + for (const client of this[kClients]) { + client[kWeight] = this[kMaxWeightPerServer] + } + + this._updateBalancedPoolStats() + + return this + } + + _updateBalancedPoolStats () { + this[kGreatestCommonDivisor] = this[kClients].map(p => p[kWeight]).reduce(getGreatestCommonDivisor, 0) + } + + removeUpstream (upstream) { + const upstreamOrigin = parseOrigin(upstream).origin + + const pool = this[kClients].find((pool) => ( + pool[kUrl].origin === upstreamOrigin && + pool.closed !== true && + pool.destroyed !== true + )) + + if (pool) { + this[kRemoveClient](pool) + } + + return this + } + + get upstreams () { + return this[kClients] + .filter(dispatcher => dispatcher.closed !== true && dispatcher.destroyed !== true) + .map((p) => p[kUrl].origin) + } + + [kGetDispatcher] () { + // We validate that pools is greater than 0, + // otherwise we would have to wait until an upstream + // is added, which might never happen. + if (this[kClients].length === 0) { + throw new BalancedPoolMissingUpstreamError() + } + + const dispatcher = this[kClients].find(dispatcher => ( + !dispatcher[kNeedDrain] && + dispatcher.closed !== true && + dispatcher.destroyed !== true + )) + + if (!dispatcher) { + return + } + + const allClientsBusy = this[kClients].map(pool => pool[kNeedDrain]).reduce((a, b) => a && b, true) + + if (allClientsBusy) { + return + } + + let counter = 0 + + let maxWeightIndex = this[kClients].findIndex(pool => !pool[kNeedDrain]) + + while (counter++ < this[kClients].length) { + this[kIndex] = (this[kIndex] + 1) % this[kClients].length + const pool = this[kClients][this[kIndex]] + + // find pool index with the largest weight + if (pool[kWeight] > this[kClients][maxWeightIndex][kWeight] && !pool[kNeedDrain]) { + maxWeightIndex = this[kIndex] + } + + // decrease the current weight every `this[kClients].length`. + if (this[kIndex] === 0) { + // Set the current weight to the next lower weight. + this[kCurrentWeight] = this[kCurrentWeight] - this[kGreatestCommonDivisor] + + if (this[kCurrentWeight] <= 0) { + this[kCurrentWeight] = this[kMaxWeightPerServer] + } + } + if (pool[kWeight] >= this[kCurrentWeight] && (!pool[kNeedDrain])) { + return pool + } + } + + this[kCurrentWeight] = this[kClients][maxWeightIndex][kWeight] + this[kIndex] = maxWeightIndex + return this[kClients][maxWeightIndex] + } +} + +module.exports = BalancedPool + + +/***/ }), + +/***/ 1308: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { kConstruct } = __nccwpck_require__(8812) +const { urlEquals, fieldValues: getFieldValues } = __nccwpck_require__(2528) +const { kEnumerableProperty, isDisturbed } = __nccwpck_require__(9522) +const { kHeadersList } = __nccwpck_require__(9440) +const { webidl } = __nccwpck_require__(1537) +const { Response, cloneResponse } = __nccwpck_require__(5796) +const { Request } = __nccwpck_require__(9157) +const { kState, kHeaders, kGuard, kRealm } = __nccwpck_require__(8085) +const { fetching } = __nccwpck_require__(5935) +const { urlIsHttpHttpsScheme, createDeferredPromise, readAllBytes } = __nccwpck_require__(784) +const assert = __nccwpck_require__(9491) +const { getGlobalDispatcher } = __nccwpck_require__(5035) + +/** + * @see https://w3c.github.io/ServiceWorker/#dfn-cache-batch-operation + * @typedef {Object} CacheBatchOperation + * @property {'delete' | 'put'} type + * @property {any} request + * @property {any} response + * @property {import('../../types/cache').CacheQueryOptions} options + */ + +/** + * @see https://w3c.github.io/ServiceWorker/#dfn-request-response-list + * @typedef {[any, any][]} requestResponseList + */ + +class Cache { + /** + * @see https://w3c.github.io/ServiceWorker/#dfn-relevant-request-response-list + * @type {requestResponseList} + */ + #relevantRequestResponseList + + constructor () { + if (arguments[0] !== kConstruct) { + webidl.illegalConstructor() + } + + this.#relevantRequestResponseList = arguments[1] + } + + async match (request, options = {}) { + webidl.brandCheck(this, Cache) + webidl.argumentLengthCheck(arguments, 1, { header: 'Cache.match' }) + + request = webidl.converters.RequestInfo(request) + options = webidl.converters.CacheQueryOptions(options) + + const p = await this.matchAll(request, options) + + if (p.length === 0) { + return + } + + return p[0] + } + + async matchAll (request = undefined, options = {}) { + webidl.brandCheck(this, Cache) + + if (request !== undefined) request = webidl.converters.RequestInfo(request) + options = webidl.converters.CacheQueryOptions(options) + + // 1. + let r = null + + // 2. + if (request !== undefined) { + if (request instanceof Request) { + // 2.1.1 + r = request[kState] + + // 2.1.2 + if (r.method !== 'GET' && !options.ignoreMethod) { + return [] + } + } else if (typeof request === 'string') { + // 2.2.1 + r = new Request(request)[kState] + } + } + + // 5. + // 5.1 + const responses = [] + + // 5.2 + if (request === undefined) { + // 5.2.1 + for (const requestResponse of this.#relevantRequestResponseList) { + responses.push(requestResponse[1]) + } + } else { // 5.3 + // 5.3.1 + const requestResponses = this.#queryCache(r, options) + + // 5.3.2 + for (const requestResponse of requestResponses) { + responses.push(requestResponse[1]) + } + } + + // 5.4 + // We don't implement CORs so we don't need to loop over the responses, yay! + + // 5.5.1 + const responseList = [] + + // 5.5.2 + for (const response of responses) { + // 5.5.2.1 + const responseObject = new Response(response.body?.source ?? null) + const body = responseObject[kState].body + responseObject[kState] = response + responseObject[kState].body = body + responseObject[kHeaders][kHeadersList] = response.headersList + responseObject[kHeaders][kGuard] = 'immutable' + + responseList.push(responseObject) + } + + // 6. + return Object.freeze(responseList) + } + + async add (request) { + webidl.brandCheck(this, Cache) + webidl.argumentLengthCheck(arguments, 1, { header: 'Cache.add' }) + + request = webidl.converters.RequestInfo(request) + + // 1. + const requests = [request] + + // 2. + const responseArrayPromise = this.addAll(requests) + + // 3. + return await responseArrayPromise + } + + async addAll (requests) { + webidl.brandCheck(this, Cache) + webidl.argumentLengthCheck(arguments, 1, { header: 'Cache.addAll' }) + + requests = webidl.converters['sequence'](requests) + + // 1. + const responsePromises = [] + + // 2. + const requestList = [] + + // 3. + for (const request of requests) { + if (typeof request === 'string') { + continue + } + + // 3.1 + const r = request[kState] + + // 3.2 + if (!urlIsHttpHttpsScheme(r.url) || r.method !== 'GET') { + throw webidl.errors.exception({ + header: 'Cache.addAll', + message: 'Expected http/s scheme when method is not GET.' + }) + } + } + + // 4. + /** @type {ReturnType[]} */ + const fetchControllers = [] + + // 5. + for (const request of requests) { + // 5.1 + const r = new Request(request)[kState] + + // 5.2 + if (!urlIsHttpHttpsScheme(r.url)) { + throw webidl.errors.exception({ + header: 'Cache.addAll', + message: 'Expected http/s scheme.' + }) + } + + // 5.4 + r.initiator = 'fetch' + r.destination = 'subresource' + + // 5.5 + requestList.push(r) + + // 5.6 + const responsePromise = createDeferredPromise() + + // 5.7 + fetchControllers.push(fetching({ + request: r, + dispatcher: getGlobalDispatcher(), + processResponse (response) { + // 1. + if (response.type === 'error' || response.status === 206 || response.status < 200 || response.status > 299) { + responsePromise.reject(webidl.errors.exception({ + header: 'Cache.addAll', + message: 'Received an invalid status code or the request failed.' + })) + } else if (response.headersList.contains('vary')) { // 2. + // 2.1 + const fieldValues = getFieldValues(response.headersList.get('vary')) + + // 2.2 + for (const fieldValue of fieldValues) { + // 2.2.1 + if (fieldValue === '*') { + responsePromise.reject(webidl.errors.exception({ + header: 'Cache.addAll', + message: 'invalid vary field value' + })) + + for (const controller of fetchControllers) { + controller.abort() + } + + return + } + } + } + }, + processResponseEndOfBody (response) { + // 1. + if (response.aborted) { + responsePromise.reject(new DOMException('aborted', 'AbortError')) + return + } + + // 2. + responsePromise.resolve(response) + } + })) + + // 5.8 + responsePromises.push(responsePromise.promise) + } + + // 6. + const p = Promise.all(responsePromises) + + // 7. + const responses = await p + + // 7.1 + const operations = [] + + // 7.2 + let index = 0 + + // 7.3 + for (const response of responses) { + // 7.3.1 + /** @type {CacheBatchOperation} */ + const operation = { + type: 'put', // 7.3.2 + request: requestList[index], // 7.3.3 + response // 7.3.4 + } + + operations.push(operation) // 7.3.5 + + index++ // 7.3.6 + } + + // 7.5 + const cacheJobPromise = createDeferredPromise() + + // 7.6.1 + let errorData = null + + // 7.6.2 + try { + this.#batchCacheOperations(operations) + } catch (e) { + errorData = e + } + + // 7.6.3 + queueMicrotask(() => { + // 7.6.3.1 + if (errorData === null) { + cacheJobPromise.resolve(undefined) + } else { + // 7.6.3.2 + cacheJobPromise.reject(errorData) + } + }) + + // 7.7 + return cacheJobPromise.promise + } + + async put (request, response) { + webidl.brandCheck(this, Cache) + webidl.argumentLengthCheck(arguments, 2, { header: 'Cache.put' }) + + request = webidl.converters.RequestInfo(request) + response = webidl.converters.Response(response) + + // 1. + let innerRequest = null + + // 2. + if (request instanceof Request) { + innerRequest = request[kState] + } else { // 3. + innerRequest = new Request(request)[kState] + } + + // 4. + if (!urlIsHttpHttpsScheme(innerRequest.url) || innerRequest.method !== 'GET') { + throw webidl.errors.exception({ + header: 'Cache.put', + message: 'Expected an http/s scheme when method is not GET' + }) + } + + // 5. + const innerResponse = response[kState] + + // 6. + if (innerResponse.status === 206) { + throw webidl.errors.exception({ + header: 'Cache.put', + message: 'Got 206 status' + }) + } + + // 7. + if (innerResponse.headersList.contains('vary')) { + // 7.1. + const fieldValues = getFieldValues(innerResponse.headersList.get('vary')) + + // 7.2. + for (const fieldValue of fieldValues) { + // 7.2.1 + if (fieldValue === '*') { + throw webidl.errors.exception({ + header: 'Cache.put', + message: 'Got * vary field value' + }) + } + } + } + + // 8. + if (innerResponse.body && (isDisturbed(innerResponse.body.stream) || innerResponse.body.stream.locked)) { + throw webidl.errors.exception({ + header: 'Cache.put', + message: 'Response body is locked or disturbed' + }) + } + + // 9. + const clonedResponse = cloneResponse(innerResponse) + + // 10. + const bodyReadPromise = createDeferredPromise() + + // 11. + if (innerResponse.body != null) { + // 11.1 + const stream = innerResponse.body.stream + + // 11.2 + const reader = stream.getReader() + + // 11.3 + readAllBytes(reader).then(bodyReadPromise.resolve, bodyReadPromise.reject) + } else { + bodyReadPromise.resolve(undefined) + } + + // 12. + /** @type {CacheBatchOperation[]} */ + const operations = [] + + // 13. + /** @type {CacheBatchOperation} */ + const operation = { + type: 'put', // 14. + request: innerRequest, // 15. + response: clonedResponse // 16. + } + + // 17. + operations.push(operation) + + // 19. + const bytes = await bodyReadPromise.promise + + if (clonedResponse.body != null) { + clonedResponse.body.source = bytes + } + + // 19.1 + const cacheJobPromise = createDeferredPromise() + + // 19.2.1 + let errorData = null + + // 19.2.2 + try { + this.#batchCacheOperations(operations) + } catch (e) { + errorData = e + } + + // 19.2.3 + queueMicrotask(() => { + // 19.2.3.1 + if (errorData === null) { + cacheJobPromise.resolve() + } else { // 19.2.3.2 + cacheJobPromise.reject(errorData) + } + }) + + return cacheJobPromise.promise + } + + async delete (request, options = {}) { + webidl.brandCheck(this, Cache) + webidl.argumentLengthCheck(arguments, 1, { header: 'Cache.delete' }) + + request = webidl.converters.RequestInfo(request) + options = webidl.converters.CacheQueryOptions(options) + + /** + * @type {Request} + */ + let r = null + + if (request instanceof Request) { + r = request[kState] + + if (r.method !== 'GET' && !options.ignoreMethod) { + return false + } + } else { + assert(typeof request === 'string') + + r = new Request(request)[kState] + } + + /** @type {CacheBatchOperation[]} */ + const operations = [] + + /** @type {CacheBatchOperation} */ + const operation = { + type: 'delete', + request: r, + options + } + + operations.push(operation) + + const cacheJobPromise = createDeferredPromise() + + let errorData = null + let requestResponses + + try { + requestResponses = this.#batchCacheOperations(operations) + } catch (e) { + errorData = e + } + + queueMicrotask(() => { + if (errorData === null) { + cacheJobPromise.resolve(!!requestResponses?.length) + } else { + cacheJobPromise.reject(errorData) + } + }) + + return cacheJobPromise.promise + } + + /** + * @see https://w3c.github.io/ServiceWorker/#dom-cache-keys + * @param {any} request + * @param {import('../../types/cache').CacheQueryOptions} options + * @returns {readonly Request[]} + */ + async keys (request = undefined, options = {}) { + webidl.brandCheck(this, Cache) + + if (request !== undefined) request = webidl.converters.RequestInfo(request) + options = webidl.converters.CacheQueryOptions(options) + + // 1. + let r = null + + // 2. + if (request !== undefined) { + // 2.1 + if (request instanceof Request) { + // 2.1.1 + r = request[kState] + + // 2.1.2 + if (r.method !== 'GET' && !options.ignoreMethod) { + return [] + } + } else if (typeof request === 'string') { // 2.2 + r = new Request(request)[kState] + } + } + + // 4. + const promise = createDeferredPromise() + + // 5. + // 5.1 + const requests = [] + + // 5.2 + if (request === undefined) { + // 5.2.1 + for (const requestResponse of this.#relevantRequestResponseList) { + // 5.2.1.1 + requests.push(requestResponse[0]) + } + } else { // 5.3 + // 5.3.1 + const requestResponses = this.#queryCache(r, options) + + // 5.3.2 + for (const requestResponse of requestResponses) { + // 5.3.2.1 + requests.push(requestResponse[0]) + } + } + + // 5.4 + queueMicrotask(() => { + // 5.4.1 + const requestList = [] + + // 5.4.2 + for (const request of requests) { + const requestObject = new Request('https://a') + requestObject[kState] = request + requestObject[kHeaders][kHeadersList] = request.headersList + requestObject[kHeaders][kGuard] = 'immutable' + requestObject[kRealm] = request.client + + // 5.4.2.1 + requestList.push(requestObject) + } + + // 5.4.3 + promise.resolve(Object.freeze(requestList)) + }) + + return promise.promise + } + + /** + * @see https://w3c.github.io/ServiceWorker/#batch-cache-operations-algorithm + * @param {CacheBatchOperation[]} operations + * @returns {requestResponseList} + */ + #batchCacheOperations (operations) { + // 1. + const cache = this.#relevantRequestResponseList + + // 2. + const backupCache = [...cache] + + // 3. + const addedItems = [] + + // 4.1 + const resultList = [] + + try { + // 4.2 + for (const operation of operations) { + // 4.2.1 + if (operation.type !== 'delete' && operation.type !== 'put') { + throw webidl.errors.exception({ + header: 'Cache.#batchCacheOperations', + message: 'operation type does not match "delete" or "put"' + }) + } + + // 4.2.2 + if (operation.type === 'delete' && operation.response != null) { + throw webidl.errors.exception({ + header: 'Cache.#batchCacheOperations', + message: 'delete operation should not have an associated response' + }) + } + + // 4.2.3 + if (this.#queryCache(operation.request, operation.options, addedItems).length) { + throw new DOMException('???', 'InvalidStateError') + } + + // 4.2.4 + let requestResponses + + // 4.2.5 + if (operation.type === 'delete') { + // 4.2.5.1 + requestResponses = this.#queryCache(operation.request, operation.options) + + // TODO: the spec is wrong, this is needed to pass WPTs + if (requestResponses.length === 0) { + return [] + } + + // 4.2.5.2 + for (const requestResponse of requestResponses) { + const idx = cache.indexOf(requestResponse) + assert(idx !== -1) + + // 4.2.5.2.1 + cache.splice(idx, 1) + } + } else if (operation.type === 'put') { // 4.2.6 + // 4.2.6.1 + if (operation.response == null) { + throw webidl.errors.exception({ + header: 'Cache.#batchCacheOperations', + message: 'put operation should have an associated response' + }) + } + + // 4.2.6.2 + const r = operation.request + + // 4.2.6.3 + if (!urlIsHttpHttpsScheme(r.url)) { + throw webidl.errors.exception({ + header: 'Cache.#batchCacheOperations', + message: 'expected http or https scheme' + }) + } + + // 4.2.6.4 + if (r.method !== 'GET') { + throw webidl.errors.exception({ + header: 'Cache.#batchCacheOperations', + message: 'not get method' + }) + } + + // 4.2.6.5 + if (operation.options != null) { + throw webidl.errors.exception({ + header: 'Cache.#batchCacheOperations', + message: 'options must not be defined' + }) + } + + // 4.2.6.6 + requestResponses = this.#queryCache(operation.request) + + // 4.2.6.7 + for (const requestResponse of requestResponses) { + const idx = cache.indexOf(requestResponse) + assert(idx !== -1) + + // 4.2.6.7.1 + cache.splice(idx, 1) + } + + // 4.2.6.8 + cache.push([operation.request, operation.response]) + + // 4.2.6.10 + addedItems.push([operation.request, operation.response]) + } + + // 4.2.7 + resultList.push([operation.request, operation.response]) + } + + // 4.3 + return resultList + } catch (e) { // 5. + // 5.1 + this.#relevantRequestResponseList.length = 0 + + // 5.2 + this.#relevantRequestResponseList = backupCache + + // 5.3 + throw e + } + } + + /** + * @see https://w3c.github.io/ServiceWorker/#query-cache + * @param {any} requestQuery + * @param {import('../../types/cache').CacheQueryOptions} options + * @param {requestResponseList} targetStorage + * @returns {requestResponseList} + */ + #queryCache (requestQuery, options, targetStorage) { + /** @type {requestResponseList} */ + const resultList = [] + + const storage = targetStorage ?? this.#relevantRequestResponseList + + for (const requestResponse of storage) { + const [cachedRequest, cachedResponse] = requestResponse + if (this.#requestMatchesCachedItem(requestQuery, cachedRequest, cachedResponse, options)) { + resultList.push(requestResponse) + } + } + + return resultList + } + + /** + * @see https://w3c.github.io/ServiceWorker/#request-matches-cached-item-algorithm + * @param {any} requestQuery + * @param {any} request + * @param {any | null} response + * @param {import('../../types/cache').CacheQueryOptions | undefined} options + * @returns {boolean} + */ + #requestMatchesCachedItem (requestQuery, request, response = null, options) { + // if (options?.ignoreMethod === false && request.method === 'GET') { + // return false + // } + + const queryURL = new URL(requestQuery.url) + + const cachedURL = new URL(request.url) + + if (options?.ignoreSearch) { + cachedURL.search = '' + + queryURL.search = '' + } + + if (!urlEquals(queryURL, cachedURL, true)) { + return false + } + + if ( + response == null || + options?.ignoreVary || + !response.headersList.contains('vary') + ) { + return true + } + + const fieldValues = getFieldValues(response.headersList.get('vary')) + + for (const fieldValue of fieldValues) { + if (fieldValue === '*') { + return false + } + + const requestValue = request.headersList.get(fieldValue) + const queryValue = requestQuery.headersList.get(fieldValue) + + // If one has the header and the other doesn't, or one has + // a different value than the other, return false + if (requestValue !== queryValue) { + return false + } + } + + return true + } +} + +Object.defineProperties(Cache.prototype, { + [Symbol.toStringTag]: { + value: 'Cache', + configurable: true + }, + match: kEnumerableProperty, + matchAll: kEnumerableProperty, + add: kEnumerableProperty, + addAll: kEnumerableProperty, + put: kEnumerableProperty, + delete: kEnumerableProperty, + keys: kEnumerableProperty +}) + +const cacheQueryOptionConverters = [ + { + key: 'ignoreSearch', + converter: webidl.converters.boolean, + defaultValue: false + }, + { + key: 'ignoreMethod', + converter: webidl.converters.boolean, + defaultValue: false + }, + { + key: 'ignoreVary', + converter: webidl.converters.boolean, + defaultValue: false + } +] + +webidl.converters.CacheQueryOptions = webidl.dictionaryConverter(cacheQueryOptionConverters) + +webidl.converters.MultiCacheQueryOptions = webidl.dictionaryConverter([ + ...cacheQueryOptionConverters, + { + key: 'cacheName', + converter: webidl.converters.DOMString + } +]) + +webidl.converters.Response = webidl.interfaceConverter(Response) + +webidl.converters['sequence'] = webidl.sequenceConverter( + webidl.converters.RequestInfo +) + +module.exports = { + Cache +} + + +/***/ }), + +/***/ 2828: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { kConstruct } = __nccwpck_require__(8812) +const { Cache } = __nccwpck_require__(1308) +const { webidl } = __nccwpck_require__(1537) +const { kEnumerableProperty } = __nccwpck_require__(9522) + +class CacheStorage { + /** + * @see https://w3c.github.io/ServiceWorker/#dfn-relevant-name-to-cache-map + * @type {Map} + */ + async has (cacheName) { + webidl.brandCheck(this, CacheStorage) + webidl.argumentLengthCheck(arguments, 1, { header: 'CacheStorage.has' }) + + cacheName = webidl.converters.DOMString(cacheName) + + // 2.1.1 + // 2.2 + return this.#caches.has(cacheName) + } + + /** + * @see https://w3c.github.io/ServiceWorker/#dom-cachestorage-open + * @param {string} cacheName + * @returns {Promise} + */ + async open (cacheName) { + webidl.brandCheck(this, CacheStorage) + webidl.argumentLengthCheck(arguments, 1, { header: 'CacheStorage.open' }) + + cacheName = webidl.converters.DOMString(cacheName) + + // 2.1 + if (this.#caches.has(cacheName)) { + // await caches.open('v1') !== await caches.open('v1') + + // 2.1.1 + const cache = this.#caches.get(cacheName) + + // 2.1.1.1 + return new Cache(kConstruct, cache) + } + + // 2.2 + const cache = [] + + // 2.3 + this.#caches.set(cacheName, cache) + + // 2.4 + return new Cache(kConstruct, cache) + } + + /** + * @see https://w3c.github.io/ServiceWorker/#cache-storage-delete + * @param {string} cacheName + * @returns {Promise} + */ + async delete (cacheName) { + webidl.brandCheck(this, CacheStorage) + webidl.argumentLengthCheck(arguments, 1, { header: 'CacheStorage.delete' }) + + cacheName = webidl.converters.DOMString(cacheName) + + return this.#caches.delete(cacheName) + } + + /** + * @see https://w3c.github.io/ServiceWorker/#cache-storage-keys + * @returns {string[]} + */ + async keys () { + webidl.brandCheck(this, CacheStorage) + + // 2.1 + const keys = this.#caches.keys() + + // 2.2 + return [...keys] + } +} + +Object.defineProperties(CacheStorage.prototype, { + [Symbol.toStringTag]: { + value: 'CacheStorage', + configurable: true + }, + match: kEnumerableProperty, + has: kEnumerableProperty, + open: kEnumerableProperty, + delete: kEnumerableProperty, + keys: kEnumerableProperty +}) + +module.exports = { + CacheStorage +} + + +/***/ }), + +/***/ 8812: +/***/ ((module) => { + +"use strict"; + + +module.exports = { + kConstruct: Symbol('constructable') +} + + +/***/ }), + +/***/ 2528: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const assert = __nccwpck_require__(9491) +const { URLSerializer } = __nccwpck_require__(2791) +const { isValidHeaderName } = __nccwpck_require__(784) + +/** + * @see https://url.spec.whatwg.org/#concept-url-equals + * @param {URL} A + * @param {URL} B + * @param {boolean | undefined} excludeFragment + * @returns {boolean} + */ +function urlEquals (A, B, excludeFragment = false) { + const serializedA = URLSerializer(A, excludeFragment) + + const serializedB = URLSerializer(B, excludeFragment) + + return serializedA === serializedB +} + +/** + * @see https://github.com/chromium/chromium/blob/694d20d134cb553d8d89e5500b9148012b1ba299/content/browser/cache_storage/cache_storage_cache.cc#L260-L262 + * @param {string} header + */ +function fieldValues (header) { + assert(header !== null) + + const values = [] + + for (let value of header.split(',')) { + value = value.trim() + + if (!value.length) { + continue + } else if (!isValidHeaderName(value)) { + continue + } + + values.push(value) + } + + return values +} + +module.exports = { + urlEquals, + fieldValues +} + + +/***/ }), + +/***/ 1180: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; +// @ts-check + + + +/* global WebAssembly */ + +const assert = __nccwpck_require__(9491) +const net = __nccwpck_require__(1808) +const http = __nccwpck_require__(3685) +const { pipeline } = __nccwpck_require__(2781) +const util = __nccwpck_require__(9522) +const timers = __nccwpck_require__(883) +const Request = __nccwpck_require__(2690) +const DispatcherBase = __nccwpck_require__(8462) +const { + RequestContentLengthMismatchError, + ResponseContentLengthMismatchError, + InvalidArgumentError, + RequestAbortedError, + HeadersTimeoutError, + HeadersOverflowError, + SocketError, + InformationalError, + BodyTimeoutError, + HTTPParserError, + ResponseExceededMaxSizeError, + ClientDestroyedError +} = __nccwpck_require__(721) +const buildConnector = __nccwpck_require__(7530) +const { + kUrl, + kReset, + kServerName, + kClient, + kBusy, + kParser, + kConnect, + kBlocking, + kResuming, + kRunning, + kPending, + kSize, + kWriting, + kQueue, + kConnected, + kConnecting, + kNeedDrain, + kNoRef, + kKeepAliveDefaultTimeout, + kHostHeader, + kPendingIdx, + kRunningIdx, + kError, + kPipelining, + kSocket, + kKeepAliveTimeoutValue, + kMaxHeadersSize, + kKeepAliveMaxTimeout, + kKeepAliveTimeoutThreshold, + kHeadersTimeout, + kBodyTimeout, + kStrictContentLength, + kConnector, + kMaxRedirections, + kMaxRequests, + kCounter, + kClose, + kDestroy, + kDispatch, + kInterceptors, + kLocalAddress, + kMaxResponseSize, + kHTTPConnVersion, + // HTTP2 + kHost, + kHTTP2Session, + kHTTP2SessionState, + kHTTP2BuildRequest, + kHTTP2CopyHeaders, + kHTTP1BuildRequest +} = __nccwpck_require__(9440) + +/** @type {import('http2')} */ +let http2 +try { + http2 = __nccwpck_require__(5158) +} catch { + // @ts-ignore + http2 = { constants: {} } +} + +const { + constants: { + HTTP2_HEADER_AUTHORITY, + HTTP2_HEADER_METHOD, + HTTP2_HEADER_PATH, + HTTP2_HEADER_SCHEME, + HTTP2_HEADER_CONTENT_LENGTH, + HTTP2_HEADER_EXPECT, + HTTP2_HEADER_STATUS + } +} = http2 + +// Experimental +let h2ExperimentalWarned = false + +const FastBuffer = Buffer[Symbol.species] + +const kClosedResolve = Symbol('kClosedResolve') + +const channels = {} + +try { + const diagnosticsChannel = __nccwpck_require__(7643) + channels.sendHeaders = diagnosticsChannel.channel('undici:client:sendHeaders') + channels.beforeConnect = diagnosticsChannel.channel('undici:client:beforeConnect') + channels.connectError = diagnosticsChannel.channel('undici:client:connectError') + channels.connected = diagnosticsChannel.channel('undici:client:connected') +} catch { + channels.sendHeaders = { hasSubscribers: false } + channels.beforeConnect = { hasSubscribers: false } + channels.connectError = { hasSubscribers: false } + channels.connected = { hasSubscribers: false } +} + +/** + * @type {import('../types/client').default} + */ +class Client extends DispatcherBase { + /** + * + * @param {string|URL} url + * @param {import('../types/client').Client.Options} options + */ + constructor (url, { + interceptors, + maxHeaderSize, + headersTimeout, + socketTimeout, + requestTimeout, + connectTimeout, + bodyTimeout, + idleTimeout, + keepAlive, + keepAliveTimeout, + maxKeepAliveTimeout, + keepAliveMaxTimeout, + keepAliveTimeoutThreshold, + socketPath, + pipelining, + tls, + strictContentLength, + maxCachedSessions, + maxRedirections, + connect, + maxRequestsPerClient, + localAddress, + maxResponseSize, + autoSelectFamily, + autoSelectFamilyAttemptTimeout, + // h2 + allowH2, + maxConcurrentStreams + } = {}) { + super() + + if (keepAlive !== undefined) { + throw new InvalidArgumentError('unsupported keepAlive, use pipelining=0 instead') + } + + if (socketTimeout !== undefined) { + throw new InvalidArgumentError('unsupported socketTimeout, use headersTimeout & bodyTimeout instead') + } + + if (requestTimeout !== undefined) { + throw new InvalidArgumentError('unsupported requestTimeout, use headersTimeout & bodyTimeout instead') + } + + if (idleTimeout !== undefined) { + throw new InvalidArgumentError('unsupported idleTimeout, use keepAliveTimeout instead') + } + + if (maxKeepAliveTimeout !== undefined) { + throw new InvalidArgumentError('unsupported maxKeepAliveTimeout, use keepAliveMaxTimeout instead') + } + + if (maxHeaderSize != null && !Number.isFinite(maxHeaderSize)) { + throw new InvalidArgumentError('invalid maxHeaderSize') + } + + if (socketPath != null && typeof socketPath !== 'string') { + throw new InvalidArgumentError('invalid socketPath') + } + + if (connectTimeout != null && (!Number.isFinite(connectTimeout) || connectTimeout < 0)) { + throw new InvalidArgumentError('invalid connectTimeout') + } + + if (keepAliveTimeout != null && (!Number.isFinite(keepAliveTimeout) || keepAliveTimeout <= 0)) { + throw new InvalidArgumentError('invalid keepAliveTimeout') + } + + if (keepAliveMaxTimeout != null && (!Number.isFinite(keepAliveMaxTimeout) || keepAliveMaxTimeout <= 0)) { + throw new InvalidArgumentError('invalid keepAliveMaxTimeout') + } + + if (keepAliveTimeoutThreshold != null && !Number.isFinite(keepAliveTimeoutThreshold)) { + throw new InvalidArgumentError('invalid keepAliveTimeoutThreshold') + } + + if (headersTimeout != null && (!Number.isInteger(headersTimeout) || headersTimeout < 0)) { + throw new InvalidArgumentError('headersTimeout must be a positive integer or zero') + } + + if (bodyTimeout != null && (!Number.isInteger(bodyTimeout) || bodyTimeout < 0)) { + throw new InvalidArgumentError('bodyTimeout must be a positive integer or zero') + } + + if (connect != null && typeof connect !== 'function' && typeof connect !== 'object') { + throw new InvalidArgumentError('connect must be a function or an object') + } + + if (maxRedirections != null && (!Number.isInteger(maxRedirections) || maxRedirections < 0)) { + throw new InvalidArgumentError('maxRedirections must be a positive number') + } + + if (maxRequestsPerClient != null && (!Number.isInteger(maxRequestsPerClient) || maxRequestsPerClient < 0)) { + throw new InvalidArgumentError('maxRequestsPerClient must be a positive number') + } + + if (localAddress != null && (typeof localAddress !== 'string' || net.isIP(localAddress) === 0)) { + throw new InvalidArgumentError('localAddress must be valid string IP address') + } + + if (maxResponseSize != null && (!Number.isInteger(maxResponseSize) || maxResponseSize < -1)) { + throw new InvalidArgumentError('maxResponseSize must be a positive number') + } + + if ( + autoSelectFamilyAttemptTimeout != null && + (!Number.isInteger(autoSelectFamilyAttemptTimeout) || autoSelectFamilyAttemptTimeout < -1) + ) { + throw new InvalidArgumentError('autoSelectFamilyAttemptTimeout must be a positive number') + } + + // h2 + if (allowH2 != null && typeof allowH2 !== 'boolean') { + throw new InvalidArgumentError('allowH2 must be a valid boolean value') + } + + if (maxConcurrentStreams != null && (typeof maxConcurrentStreams !== 'number' || maxConcurrentStreams < 1)) { + throw new InvalidArgumentError('maxConcurrentStreams must be a possitive integer, greater than 0') + } + + if (typeof connect !== 'function') { + connect = buildConnector({ + ...tls, + maxCachedSessions, + allowH2, + socketPath, + timeout: connectTimeout, + ...(util.nodeHasAutoSelectFamily && autoSelectFamily ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : undefined), + ...connect + }) + } + + this[kInterceptors] = interceptors && interceptors.Client && Array.isArray(interceptors.Client) + ? interceptors.Client + : [createRedirectInterceptor({ maxRedirections })] + this[kUrl] = util.parseOrigin(url) + this[kConnector] = connect + this[kSocket] = null + this[kPipelining] = pipelining != null ? pipelining : 1 + this[kMaxHeadersSize] = maxHeaderSize || http.maxHeaderSize + this[kKeepAliveDefaultTimeout] = keepAliveTimeout == null ? 4e3 : keepAliveTimeout + this[kKeepAliveMaxTimeout] = keepAliveMaxTimeout == null ? 600e3 : keepAliveMaxTimeout + this[kKeepAliveTimeoutThreshold] = keepAliveTimeoutThreshold == null ? 1e3 : keepAliveTimeoutThreshold + this[kKeepAliveTimeoutValue] = this[kKeepAliveDefaultTimeout] + this[kServerName] = null + this[kLocalAddress] = localAddress != null ? localAddress : null + this[kResuming] = 0 // 0, idle, 1, scheduled, 2 resuming + this[kNeedDrain] = 0 // 0, idle, 1, scheduled, 2 resuming + this[kHostHeader] = `host: ${this[kUrl].hostname}${this[kUrl].port ? `:${this[kUrl].port}` : ''}\r\n` + this[kBodyTimeout] = bodyTimeout != null ? bodyTimeout : 300e3 + this[kHeadersTimeout] = headersTimeout != null ? headersTimeout : 300e3 + this[kStrictContentLength] = strictContentLength == null ? true : strictContentLength + this[kMaxRedirections] = maxRedirections + this[kMaxRequests] = maxRequestsPerClient + this[kClosedResolve] = null + this[kMaxResponseSize] = maxResponseSize > -1 ? maxResponseSize : -1 + this[kHTTPConnVersion] = 'h1' + + // HTTP/2 + this[kHTTP2Session] = null + this[kHTTP2SessionState] = !allowH2 + ? null + : { + // streams: null, // Fixed queue of streams - For future support of `push` + openStreams: 0, // Keep track of them to decide wether or not unref the session + maxConcurrentStreams: maxConcurrentStreams != null ? maxConcurrentStreams : 100 // Max peerConcurrentStreams for a Node h2 server + } + this[kHost] = `${this[kUrl].hostname}${this[kUrl].port ? `:${this[kUrl].port}` : ''}` + + // kQueue is built up of 3 sections separated by + // the kRunningIdx and kPendingIdx indices. + // | complete | running | pending | + // ^ kRunningIdx ^ kPendingIdx ^ kQueue.length + // kRunningIdx points to the first running element. + // kPendingIdx points to the first pending element. + // This implements a fast queue with an amortized + // time of O(1). + + this[kQueue] = [] + this[kRunningIdx] = 0 + this[kPendingIdx] = 0 + } + + get pipelining () { + return this[kPipelining] + } + + set pipelining (value) { + this[kPipelining] = value + resume(this, true) + } + + get [kPending] () { + return this[kQueue].length - this[kPendingIdx] + } + + get [kRunning] () { + return this[kPendingIdx] - this[kRunningIdx] + } + + get [kSize] () { + return this[kQueue].length - this[kRunningIdx] + } + + get [kConnected] () { + return !!this[kSocket] && !this[kConnecting] && !this[kSocket].destroyed + } + + get [kBusy] () { + const socket = this[kSocket] + return ( + (socket && (socket[kReset] || socket[kWriting] || socket[kBlocking])) || + (this[kSize] >= (this[kPipelining] || 1)) || + this[kPending] > 0 + ) + } + + /* istanbul ignore: only used for test */ + [kConnect] (cb) { + connect(this) + this.once('connect', cb) + } + + [kDispatch] (opts, handler) { + const origin = opts.origin || this[kUrl].origin + + const request = this[kHTTPConnVersion] === 'h2' + ? Request[kHTTP2BuildRequest](origin, opts, handler) + : Request[kHTTP1BuildRequest](origin, opts, handler) + + this[kQueue].push(request) + if (this[kResuming]) { + // Do nothing. + } else if (util.bodyLength(request.body) == null && util.isIterable(request.body)) { + // Wait a tick in case stream/iterator is ended in the same tick. + this[kResuming] = 1 + process.nextTick(resume, this) + } else { + resume(this, true) + } + + if (this[kResuming] && this[kNeedDrain] !== 2 && this[kBusy]) { + this[kNeedDrain] = 2 + } + + return this[kNeedDrain] < 2 + } + + async [kClose] () { + // TODO: for H2 we need to gracefully flush the remaining enqueued + // request and close each stream. + return new Promise((resolve) => { + if (!this[kSize]) { + resolve(null) + } else { + this[kClosedResolve] = resolve + } + }) + } + + async [kDestroy] (err) { + return new Promise((resolve) => { + const requests = this[kQueue].splice(this[kPendingIdx]) + for (let i = 0; i < requests.length; i++) { + const request = requests[i] + errorRequest(this, request, err) + } + + const callback = () => { + if (this[kClosedResolve]) { + // TODO (fix): Should we error here with ClientDestroyedError? + this[kClosedResolve]() + this[kClosedResolve] = null + } + resolve() + } + + if (this[kHTTP2Session] != null) { + util.destroy(this[kHTTP2Session], err) + this[kHTTP2Session] = null + this[kHTTP2SessionState] = null + } + + if (!this[kSocket]) { + queueMicrotask(callback) + } else { + util.destroy(this[kSocket].on('close', callback), err) + } + + resume(this) + }) + } +} + +function onHttp2SessionError (err) { + assert(err.code !== 'ERR_TLS_CERT_ALTNAME_INVALID') + + this[kSocket][kError] = err + + onError(this[kClient], err) +} + +function onHttp2FrameError (type, code, id) { + const err = new InformationalError(`HTTP/2: "frameError" received - type ${type}, code ${code}`) + + if (id === 0) { + this[kSocket][kError] = err + onError(this[kClient], err) + } +} + +function onHttp2SessionEnd () { + util.destroy(this, new SocketError('other side closed')) + util.destroy(this[kSocket], new SocketError('other side closed')) +} + +function onHTTP2GoAway (code) { + const client = this[kClient] + const err = new InformationalError(`HTTP/2: "GOAWAY" frame received with code ${code}`) + client[kSocket] = null + client[kHTTP2Session] = null + + if (client.destroyed) { + assert(this[kPending] === 0) + + // Fail entire queue. + const requests = client[kQueue].splice(client[kRunningIdx]) + for (let i = 0; i < requests.length; i++) { + const request = requests[i] + errorRequest(this, request, err) + } + } else if (client[kRunning] > 0) { + // Fail head of pipeline. + const request = client[kQueue][client[kRunningIdx]] + client[kQueue][client[kRunningIdx]++] = null + + errorRequest(client, request, err) + } + + client[kPendingIdx] = client[kRunningIdx] + + assert(client[kRunning] === 0) + + client.emit('disconnect', + client[kUrl], + [client], + err + ) + + resume(client) +} + +const constants = __nccwpck_require__(5153) +const createRedirectInterceptor = __nccwpck_require__(5260) +const EMPTY_BUF = Buffer.alloc(0) + +async function lazyllhttp () { + const llhttpWasmData = process.env.JEST_WORKER_ID ? __nccwpck_require__(4650) : undefined + + let mod + try { + mod = await WebAssembly.compile(Buffer.from(__nccwpck_require__(449), 'base64')) + } catch (e) { + /* istanbul ignore next */ + + // We could check if the error was caused by the simd option not + // being enabled, but the occurring of this other error + // * https://github.com/emscripten-core/emscripten/issues/11495 + // got me to remove that check to avoid breaking Node 12. + mod = await WebAssembly.compile(Buffer.from(llhttpWasmData || __nccwpck_require__(4650), 'base64')) + } + + return await WebAssembly.instantiate(mod, { + env: { + /* eslint-disable camelcase */ + + wasm_on_url: (p, at, len) => { + /* istanbul ignore next */ + return 0 + }, + wasm_on_status: (p, at, len) => { + assert.strictEqual(currentParser.ptr, p) + const start = at - currentBufferPtr + currentBufferRef.byteOffset + return currentParser.onStatus(new FastBuffer(currentBufferRef.buffer, start, len)) || 0 + }, + wasm_on_message_begin: (p) => { + assert.strictEqual(currentParser.ptr, p) + return currentParser.onMessageBegin() || 0 + }, + wasm_on_header_field: (p, at, len) => { + assert.strictEqual(currentParser.ptr, p) + const start = at - currentBufferPtr + currentBufferRef.byteOffset + return currentParser.onHeaderField(new FastBuffer(currentBufferRef.buffer, start, len)) || 0 + }, + wasm_on_header_value: (p, at, len) => { + assert.strictEqual(currentParser.ptr, p) + const start = at - currentBufferPtr + currentBufferRef.byteOffset + return currentParser.onHeaderValue(new FastBuffer(currentBufferRef.buffer, start, len)) || 0 + }, + wasm_on_headers_complete: (p, statusCode, upgrade, shouldKeepAlive) => { + assert.strictEqual(currentParser.ptr, p) + return currentParser.onHeadersComplete(statusCode, Boolean(upgrade), Boolean(shouldKeepAlive)) || 0 + }, + wasm_on_body: (p, at, len) => { + assert.strictEqual(currentParser.ptr, p) + const start = at - currentBufferPtr + currentBufferRef.byteOffset + return currentParser.onBody(new FastBuffer(currentBufferRef.buffer, start, len)) || 0 + }, + wasm_on_message_complete: (p) => { + assert.strictEqual(currentParser.ptr, p) + return currentParser.onMessageComplete() || 0 + } + + /* eslint-enable camelcase */ + } + }) +} + +let llhttpInstance = null +let llhttpPromise = lazyllhttp() +llhttpPromise.catch() + +let currentParser = null +let currentBufferRef = null +let currentBufferSize = 0 +let currentBufferPtr = null + +const TIMEOUT_HEADERS = 1 +const TIMEOUT_BODY = 2 +const TIMEOUT_IDLE = 3 + +class Parser { + constructor (client, socket, { exports }) { + assert(Number.isFinite(client[kMaxHeadersSize]) && client[kMaxHeadersSize] > 0) + + this.llhttp = exports + this.ptr = this.llhttp.llhttp_alloc(constants.TYPE.RESPONSE) + this.client = client + this.socket = socket + this.timeout = null + this.timeoutValue = null + this.timeoutType = null + this.statusCode = null + this.statusText = '' + this.upgrade = false + this.headers = [] + this.headersSize = 0 + this.headersMaxSize = client[kMaxHeadersSize] + this.shouldKeepAlive = false + this.paused = false + this.resume = this.resume.bind(this) + + this.bytesRead = 0 + + this.keepAlive = '' + this.contentLength = '' + this.connection = '' + this.maxResponseSize = client[kMaxResponseSize] + } + + setTimeout (value, type) { + this.timeoutType = type + if (value !== this.timeoutValue) { + timers.clearTimeout(this.timeout) + if (value) { + this.timeout = timers.setTimeout(onParserTimeout, value, this) + // istanbul ignore else: only for jest + if (this.timeout.unref) { + this.timeout.unref() + } + } else { + this.timeout = null + } + this.timeoutValue = value + } else if (this.timeout) { + // istanbul ignore else: only for jest + if (this.timeout.refresh) { + this.timeout.refresh() + } + } + } + + resume () { + if (this.socket.destroyed || !this.paused) { + return + } + + assert(this.ptr != null) + assert(currentParser == null) + + this.llhttp.llhttp_resume(this.ptr) + + assert(this.timeoutType === TIMEOUT_BODY) + if (this.timeout) { + // istanbul ignore else: only for jest + if (this.timeout.refresh) { + this.timeout.refresh() + } + } + + this.paused = false + this.execute(this.socket.read() || EMPTY_BUF) // Flush parser. + this.readMore() + } + + readMore () { + while (!this.paused && this.ptr) { + const chunk = this.socket.read() + if (chunk === null) { + break + } + this.execute(chunk) + } + } + + execute (data) { + assert(this.ptr != null) + assert(currentParser == null) + assert(!this.paused) + + const { socket, llhttp } = this + + if (data.length > currentBufferSize) { + if (currentBufferPtr) { + llhttp.free(currentBufferPtr) + } + currentBufferSize = Math.ceil(data.length / 4096) * 4096 + currentBufferPtr = llhttp.malloc(currentBufferSize) + } + + new Uint8Array(llhttp.memory.buffer, currentBufferPtr, currentBufferSize).set(data) + + // Call `execute` on the wasm parser. + // We pass the `llhttp_parser` pointer address, the pointer address of buffer view data, + // and finally the length of bytes to parse. + // The return value is an error code or `constants.ERROR.OK`. + try { + let ret + + try { + currentBufferRef = data + currentParser = this + ret = llhttp.llhttp_execute(this.ptr, currentBufferPtr, data.length) + /* eslint-disable-next-line no-useless-catch */ + } catch (err) { + /* istanbul ignore next: difficult to make a test case for */ + throw err + } finally { + currentParser = null + currentBufferRef = null + } + + const offset = llhttp.llhttp_get_error_pos(this.ptr) - currentBufferPtr + + if (ret === constants.ERROR.PAUSED_UPGRADE) { + this.onUpgrade(data.slice(offset)) + } else if (ret === constants.ERROR.PAUSED) { + this.paused = true + socket.unshift(data.slice(offset)) + } else if (ret !== constants.ERROR.OK) { + const ptr = llhttp.llhttp_get_error_reason(this.ptr) + let message = '' + /* istanbul ignore else: difficult to make a test case for */ + if (ptr) { + const len = new Uint8Array(llhttp.memory.buffer, ptr).indexOf(0) + message = + 'Response does not match the HTTP/1.1 protocol (' + + Buffer.from(llhttp.memory.buffer, ptr, len).toString() + + ')' + } + throw new HTTPParserError(message, constants.ERROR[ret], data.slice(offset)) + } + } catch (err) { + util.destroy(socket, err) + } + } + + destroy () { + assert(this.ptr != null) + assert(currentParser == null) + + this.llhttp.llhttp_free(this.ptr) + this.ptr = null + + timers.clearTimeout(this.timeout) + this.timeout = null + this.timeoutValue = null + this.timeoutType = null + + this.paused = false + } + + onStatus (buf) { + this.statusText = buf.toString() + } + + onMessageBegin () { + const { socket, client } = this + + /* istanbul ignore next: difficult to make a test case for */ + if (socket.destroyed) { + return -1 + } + + const request = client[kQueue][client[kRunningIdx]] + if (!request) { + return -1 + } + } + + onHeaderField (buf) { + const len = this.headers.length + + if ((len & 1) === 0) { + this.headers.push(buf) + } else { + this.headers[len - 1] = Buffer.concat([this.headers[len - 1], buf]) + } + + this.trackHeader(buf.length) + } + + onHeaderValue (buf) { + let len = this.headers.length + + if ((len & 1) === 1) { + this.headers.push(buf) + len += 1 + } else { + this.headers[len - 1] = Buffer.concat([this.headers[len - 1], buf]) + } + + const key = this.headers[len - 2] + if (key.length === 10 && key.toString().toLowerCase() === 'keep-alive') { + this.keepAlive += buf.toString() + } else if (key.length === 10 && key.toString().toLowerCase() === 'connection') { + this.connection += buf.toString() + } else if (key.length === 14 && key.toString().toLowerCase() === 'content-length') { + this.contentLength += buf.toString() + } + + this.trackHeader(buf.length) + } + + trackHeader (len) { + this.headersSize += len + if (this.headersSize >= this.headersMaxSize) { + util.destroy(this.socket, new HeadersOverflowError()) + } + } + + onUpgrade (head) { + const { upgrade, client, socket, headers, statusCode } = this + + assert(upgrade) + + const request = client[kQueue][client[kRunningIdx]] + assert(request) + + assert(!socket.destroyed) + assert(socket === client[kSocket]) + assert(!this.paused) + assert(request.upgrade || request.method === 'CONNECT') + + this.statusCode = null + this.statusText = '' + this.shouldKeepAlive = null + + assert(this.headers.length % 2 === 0) + this.headers = [] + this.headersSize = 0 + + socket.unshift(head) + + socket[kParser].destroy() + socket[kParser] = null + + socket[kClient] = null + socket[kError] = null + socket + .removeListener('error', onSocketError) + .removeListener('readable', onSocketReadable) + .removeListener('end', onSocketEnd) + .removeListener('close', onSocketClose) + + client[kSocket] = null + client[kQueue][client[kRunningIdx]++] = null + client.emit('disconnect', client[kUrl], [client], new InformationalError('upgrade')) + + try { + request.onUpgrade(statusCode, headers, socket) + } catch (err) { + util.destroy(socket, err) + } + + resume(client) + } + + onHeadersComplete (statusCode, upgrade, shouldKeepAlive) { + const { client, socket, headers, statusText } = this + + /* istanbul ignore next: difficult to make a test case for */ + if (socket.destroyed) { + return -1 + } + + const request = client[kQueue][client[kRunningIdx]] + + /* istanbul ignore next: difficult to make a test case for */ + if (!request) { + return -1 + } + + assert(!this.upgrade) + assert(this.statusCode < 200) + + if (statusCode === 100) { + util.destroy(socket, new SocketError('bad response', util.getSocketInfo(socket))) + return -1 + } + + /* this can only happen if server is misbehaving */ + if (upgrade && !request.upgrade) { + util.destroy(socket, new SocketError('bad upgrade', util.getSocketInfo(socket))) + return -1 + } + + assert.strictEqual(this.timeoutType, TIMEOUT_HEADERS) + + this.statusCode = statusCode + this.shouldKeepAlive = ( + shouldKeepAlive || + // Override llhttp value which does not allow keepAlive for HEAD. + (request.method === 'HEAD' && !socket[kReset] && this.connection.toLowerCase() === 'keep-alive') + ) + + if (this.statusCode >= 200) { + const bodyTimeout = request.bodyTimeout != null + ? request.bodyTimeout + : client[kBodyTimeout] + this.setTimeout(bodyTimeout, TIMEOUT_BODY) + } else if (this.timeout) { + // istanbul ignore else: only for jest + if (this.timeout.refresh) { + this.timeout.refresh() + } + } + + if (request.method === 'CONNECT') { + assert(client[kRunning] === 1) + this.upgrade = true + return 2 + } + + if (upgrade) { + assert(client[kRunning] === 1) + this.upgrade = true + return 2 + } + + assert(this.headers.length % 2 === 0) + this.headers = [] + this.headersSize = 0 + + if (this.shouldKeepAlive && client[kPipelining]) { + const keepAliveTimeout = this.keepAlive ? util.parseKeepAliveTimeout(this.keepAlive) : null + + if (keepAliveTimeout != null) { + const timeout = Math.min( + keepAliveTimeout - client[kKeepAliveTimeoutThreshold], + client[kKeepAliveMaxTimeout] + ) + if (timeout <= 0) { + socket[kReset] = true + } else { + client[kKeepAliveTimeoutValue] = timeout + } + } else { + client[kKeepAliveTimeoutValue] = client[kKeepAliveDefaultTimeout] + } + } else { + // Stop more requests from being dispatched. + socket[kReset] = true + } + + const pause = request.onHeaders(statusCode, headers, this.resume, statusText) === false + + if (request.aborted) { + return -1 + } + + if (request.method === 'HEAD') { + return 1 + } + + if (statusCode < 200) { + return 1 + } + + if (socket[kBlocking]) { + socket[kBlocking] = false + resume(client) + } + + return pause ? constants.ERROR.PAUSED : 0 + } + + onBody (buf) { + const { client, socket, statusCode, maxResponseSize } = this + + if (socket.destroyed) { + return -1 + } + + const request = client[kQueue][client[kRunningIdx]] + assert(request) + + assert.strictEqual(this.timeoutType, TIMEOUT_BODY) + if (this.timeout) { + // istanbul ignore else: only for jest + if (this.timeout.refresh) { + this.timeout.refresh() + } + } + + assert(statusCode >= 200) + + if (maxResponseSize > -1 && this.bytesRead + buf.length > maxResponseSize) { + util.destroy(socket, new ResponseExceededMaxSizeError()) + return -1 + } + + this.bytesRead += buf.length + + if (request.onData(buf) === false) { + return constants.ERROR.PAUSED + } + } + + onMessageComplete () { + const { client, socket, statusCode, upgrade, headers, contentLength, bytesRead, shouldKeepAlive } = this + + if (socket.destroyed && (!statusCode || shouldKeepAlive)) { + return -1 + } + + if (upgrade) { + return + } + + const request = client[kQueue][client[kRunningIdx]] + assert(request) + + assert(statusCode >= 100) + + this.statusCode = null + this.statusText = '' + this.bytesRead = 0 + this.contentLength = '' + this.keepAlive = '' + this.connection = '' + + assert(this.headers.length % 2 === 0) + this.headers = [] + this.headersSize = 0 + + if (statusCode < 200) { + return + } + + /* istanbul ignore next: should be handled by llhttp? */ + if (request.method !== 'HEAD' && contentLength && bytesRead !== parseInt(contentLength, 10)) { + util.destroy(socket, new ResponseContentLengthMismatchError()) + return -1 + } + + request.onComplete(headers) + + client[kQueue][client[kRunningIdx]++] = null + + if (socket[kWriting]) { + assert.strictEqual(client[kRunning], 0) + // Response completed before request. + util.destroy(socket, new InformationalError('reset')) + return constants.ERROR.PAUSED + } else if (!shouldKeepAlive) { + util.destroy(socket, new InformationalError('reset')) + return constants.ERROR.PAUSED + } else if (socket[kReset] && client[kRunning] === 0) { + // Destroy socket once all requests have completed. + // The request at the tail of the pipeline is the one + // that requested reset and no further requests should + // have been queued since then. + util.destroy(socket, new InformationalError('reset')) + return constants.ERROR.PAUSED + } else if (client[kPipelining] === 1) { + // We must wait a full event loop cycle to reuse this socket to make sure + // that non-spec compliant servers are not closing the connection even if they + // said they won't. + setImmediate(resume, client) + } else { + resume(client) + } + } +} + +function onParserTimeout (parser) { + const { socket, timeoutType, client } = parser + + /* istanbul ignore else */ + if (timeoutType === TIMEOUT_HEADERS) { + if (!socket[kWriting] || socket.writableNeedDrain || client[kRunning] > 1) { + assert(!parser.paused, 'cannot be paused while waiting for headers') + util.destroy(socket, new HeadersTimeoutError()) + } + } else if (timeoutType === TIMEOUT_BODY) { + if (!parser.paused) { + util.destroy(socket, new BodyTimeoutError()) + } + } else if (timeoutType === TIMEOUT_IDLE) { + assert(client[kRunning] === 0 && client[kKeepAliveTimeoutValue]) + util.destroy(socket, new InformationalError('socket idle timeout')) + } +} + +function onSocketReadable () { + const { [kParser]: parser } = this + if (parser) { + parser.readMore() + } +} + +function onSocketError (err) { + const { [kClient]: client, [kParser]: parser } = this + + assert(err.code !== 'ERR_TLS_CERT_ALTNAME_INVALID') + + if (client[kHTTPConnVersion] !== 'h2') { + // On Mac OS, we get an ECONNRESET even if there is a full body to be forwarded + // to the user. + if (err.code === 'ECONNRESET' && parser.statusCode && !parser.shouldKeepAlive) { + // We treat all incoming data so for as a valid response. + parser.onMessageComplete() + return + } + } + + this[kError] = err + + onError(this[kClient], err) +} + +function onError (client, err) { + if ( + client[kRunning] === 0 && + err.code !== 'UND_ERR_INFO' && + err.code !== 'UND_ERR_SOCKET' + ) { + // Error is not caused by running request and not a recoverable + // socket error. + + assert(client[kPendingIdx] === client[kRunningIdx]) + + const requests = client[kQueue].splice(client[kRunningIdx]) + for (let i = 0; i < requests.length; i++) { + const request = requests[i] + errorRequest(client, request, err) + } + assert(client[kSize] === 0) + } +} + +function onSocketEnd () { + const { [kParser]: parser, [kClient]: client } = this + + if (client[kHTTPConnVersion] !== 'h2') { + if (parser.statusCode && !parser.shouldKeepAlive) { + // We treat all incoming data so far as a valid response. + parser.onMessageComplete() + return + } + } + + util.destroy(this, new SocketError('other side closed', util.getSocketInfo(this))) +} + +function onSocketClose () { + const { [kClient]: client, [kParser]: parser } = this + + if (client[kHTTPConnVersion] === 'h1' && parser) { + if (!this[kError] && parser.statusCode && !parser.shouldKeepAlive) { + // We treat all incoming data so far as a valid response. + parser.onMessageComplete() + } + + this[kParser].destroy() + this[kParser] = null + } + + const err = this[kError] || new SocketError('closed', util.getSocketInfo(this)) + + client[kSocket] = null + + if (client.destroyed) { + assert(client[kPending] === 0) + + // Fail entire queue. + const requests = client[kQueue].splice(client[kRunningIdx]) + for (let i = 0; i < requests.length; i++) { + const request = requests[i] + errorRequest(client, request, err) + } + } else if (client[kRunning] > 0 && err.code !== 'UND_ERR_INFO') { + // Fail head of pipeline. + const request = client[kQueue][client[kRunningIdx]] + client[kQueue][client[kRunningIdx]++] = null + + errorRequest(client, request, err) + } + + client[kPendingIdx] = client[kRunningIdx] + + assert(client[kRunning] === 0) + + client.emit('disconnect', client[kUrl], [client], err) + + resume(client) +} + +async function connect (client) { + assert(!client[kConnecting]) + assert(!client[kSocket]) + + let { host, hostname, protocol, port } = client[kUrl] + + // Resolve ipv6 + if (hostname[0] === '[') { + const idx = hostname.indexOf(']') + + assert(idx !== -1) + const ip = hostname.substring(1, idx) + + assert(net.isIP(ip)) + hostname = ip + } + + client[kConnecting] = true + + if (channels.beforeConnect.hasSubscribers) { + channels.beforeConnect.publish({ + connectParams: { + host, + hostname, + protocol, + port, + servername: client[kServerName], + localAddress: client[kLocalAddress] + }, + connector: client[kConnector] + }) + } + + try { + const socket = await new Promise((resolve, reject) => { + client[kConnector]({ + host, + hostname, + protocol, + port, + servername: client[kServerName], + localAddress: client[kLocalAddress] + }, (err, socket) => { + if (err) { + reject(err) + } else { + resolve(socket) + } + }) + }) + + if (client.destroyed) { + util.destroy(socket.on('error', () => {}), new ClientDestroyedError()) + return + } + + client[kConnecting] = false + + assert(socket) + + const isH2 = socket.alpnProtocol === 'h2' + if (isH2) { + if (!h2ExperimentalWarned) { + h2ExperimentalWarned = true + process.emitWarning('H2 support is experimental, expect them to change at any time.', { + code: 'UNDICI-H2' + }) + } + + const session = http2.connect(client[kUrl], { + createConnection: () => socket, + peerMaxConcurrentStreams: client[kHTTP2SessionState].maxConcurrentStreams + }) + + client[kHTTPConnVersion] = 'h2' + session[kClient] = client + session[kSocket] = socket + session.on('error', onHttp2SessionError) + session.on('frameError', onHttp2FrameError) + session.on('end', onHttp2SessionEnd) + session.on('goaway', onHTTP2GoAway) + session.on('close', onSocketClose) + session.unref() + + client[kHTTP2Session] = session + socket[kHTTP2Session] = session + } else { + if (!llhttpInstance) { + llhttpInstance = await llhttpPromise + llhttpPromise = null + } + + socket[kNoRef] = false + socket[kWriting] = false + socket[kReset] = false + socket[kBlocking] = false + socket[kParser] = new Parser(client, socket, llhttpInstance) + } + + socket[kCounter] = 0 + socket[kMaxRequests] = client[kMaxRequests] + socket[kClient] = client + socket[kError] = null + + socket + .on('error', onSocketError) + .on('readable', onSocketReadable) + .on('end', onSocketEnd) + .on('close', onSocketClose) + + client[kSocket] = socket + + if (channels.connected.hasSubscribers) { + channels.connected.publish({ + connectParams: { + host, + hostname, + protocol, + port, + servername: client[kServerName], + localAddress: client[kLocalAddress] + }, + connector: client[kConnector], + socket + }) + } + client.emit('connect', client[kUrl], [client]) + } catch (err) { + if (client.destroyed) { + return + } + + client[kConnecting] = false + + if (channels.connectError.hasSubscribers) { + channels.connectError.publish({ + connectParams: { + host, + hostname, + protocol, + port, + servername: client[kServerName], + localAddress: client[kLocalAddress] + }, + connector: client[kConnector], + error: err + }) + } + + if (err.code === 'ERR_TLS_CERT_ALTNAME_INVALID') { + assert(client[kRunning] === 0) + while (client[kPending] > 0 && client[kQueue][client[kPendingIdx]].servername === client[kServerName]) { + const request = client[kQueue][client[kPendingIdx]++] + errorRequest(client, request, err) + } + } else { + onError(client, err) + } + + client.emit('connectionError', client[kUrl], [client], err) + } + + resume(client) +} + +function emitDrain (client) { + client[kNeedDrain] = 0 + client.emit('drain', client[kUrl], [client]) +} + +function resume (client, sync) { + if (client[kResuming] === 2) { + return + } + + client[kResuming] = 2 + + _resume(client, sync) + client[kResuming] = 0 + + if (client[kRunningIdx] > 256) { + client[kQueue].splice(0, client[kRunningIdx]) + client[kPendingIdx] -= client[kRunningIdx] + client[kRunningIdx] = 0 + } +} + +function _resume (client, sync) { + while (true) { + if (client.destroyed) { + assert(client[kPending] === 0) + return + } + + if (client[kClosedResolve] && !client[kSize]) { + client[kClosedResolve]() + client[kClosedResolve] = null + return + } + + const socket = client[kSocket] + + if (socket && !socket.destroyed && socket.alpnProtocol !== 'h2') { + if (client[kSize] === 0) { + if (!socket[kNoRef] && socket.unref) { + socket.unref() + socket[kNoRef] = true + } + } else if (socket[kNoRef] && socket.ref) { + socket.ref() + socket[kNoRef] = false + } + + if (client[kSize] === 0) { + if (socket[kParser].timeoutType !== TIMEOUT_IDLE) { + socket[kParser].setTimeout(client[kKeepAliveTimeoutValue], TIMEOUT_IDLE) + } + } else if (client[kRunning] > 0 && socket[kParser].statusCode < 200) { + if (socket[kParser].timeoutType !== TIMEOUT_HEADERS) { + const request = client[kQueue][client[kRunningIdx]] + const headersTimeout = request.headersTimeout != null + ? request.headersTimeout + : client[kHeadersTimeout] + socket[kParser].setTimeout(headersTimeout, TIMEOUT_HEADERS) + } + } + } + + if (client[kBusy]) { + client[kNeedDrain] = 2 + } else if (client[kNeedDrain] === 2) { + if (sync) { + client[kNeedDrain] = 1 + process.nextTick(emitDrain, client) + } else { + emitDrain(client) + } + continue + } + + if (client[kPending] === 0) { + return + } + + if (client[kRunning] >= (client[kPipelining] || 1)) { + return + } + + const request = client[kQueue][client[kPendingIdx]] + + if (client[kUrl].protocol === 'https:' && client[kServerName] !== request.servername) { + if (client[kRunning] > 0) { + return + } + + client[kServerName] = request.servername + + if (socket && socket.servername !== request.servername) { + util.destroy(socket, new InformationalError('servername changed')) + return + } + } + + if (client[kConnecting]) { + return + } + + if (!socket && !client[kHTTP2Session]) { + connect(client) + return + } + + if (socket.destroyed || socket[kWriting] || socket[kReset] || socket[kBlocking]) { + return + } + + if (client[kRunning] > 0 && !request.idempotent) { + // Non-idempotent request cannot be retried. + // Ensure that no other requests are inflight and + // could cause failure. + return + } + + if (client[kRunning] > 0 && (request.upgrade || request.method === 'CONNECT')) { + // Don't dispatch an upgrade until all preceding requests have completed. + // A misbehaving server might upgrade the connection before all pipelined + // request has completed. + return + } + + if (client[kRunning] > 0 && util.bodyLength(request.body) !== 0 && + (util.isStream(request.body) || util.isAsyncIterable(request.body))) { + // Request with stream or iterator body can error while other requests + // are inflight and indirectly error those as well. + // Ensure this doesn't happen by waiting for inflight + // to complete before dispatching. + + // Request with stream or iterator body cannot be retried. + // Ensure that no other requests are inflight and + // could cause failure. + return + } + + if (!request.aborted && write(client, request)) { + client[kPendingIdx]++ + } else { + client[kQueue].splice(client[kPendingIdx], 1) + } + } +} + +// https://www.rfc-editor.org/rfc/rfc7230#section-3.3.2 +function shouldSendContentLength (method) { + return method !== 'GET' && method !== 'HEAD' && method !== 'OPTIONS' && method !== 'TRACE' && method !== 'CONNECT' +} + +function write (client, request) { + if (client[kHTTPConnVersion] === 'h2') { + writeH2(client, client[kHTTP2Session], request) + return + } + + const { body, method, path, host, upgrade, headers, blocking, reset } = request + + // https://tools.ietf.org/html/rfc7231#section-4.3.1 + // https://tools.ietf.org/html/rfc7231#section-4.3.2 + // https://tools.ietf.org/html/rfc7231#section-4.3.5 + + // Sending a payload body on a request that does not + // expect it can cause undefined behavior on some + // servers and corrupt connection state. Do not + // re-use the connection for further requests. + + const expectsPayload = ( + method === 'PUT' || + method === 'POST' || + method === 'PATCH' + ) + + if (body && typeof body.read === 'function') { + // Try to read EOF in order to get length. + body.read(0) + } + + const bodyLength = util.bodyLength(body) + + let contentLength = bodyLength + + if (contentLength === null) { + contentLength = request.contentLength + } + + if (contentLength === 0 && !expectsPayload) { + // https://tools.ietf.org/html/rfc7230#section-3.3.2 + // A user agent SHOULD NOT send a Content-Length header field when + // the request message does not contain a payload body and the method + // semantics do not anticipate such a body. + + contentLength = null + } + + // https://github.com/nodejs/undici/issues/2046 + // A user agent may send a Content-Length header with 0 value, this should be allowed. + if (shouldSendContentLength(method) && contentLength > 0 && request.contentLength !== null && request.contentLength !== contentLength) { + if (client[kStrictContentLength]) { + errorRequest(client, request, new RequestContentLengthMismatchError()) + return false + } + + process.emitWarning(new RequestContentLengthMismatchError()) + } + + const socket = client[kSocket] + + try { + request.onConnect((err) => { + if (request.aborted || request.completed) { + return + } + + errorRequest(client, request, err || new RequestAbortedError()) + + util.destroy(socket, new InformationalError('aborted')) + }) + } catch (err) { + errorRequest(client, request, err) + } + + if (request.aborted) { + return false + } + + if (method === 'HEAD') { + // https://github.com/mcollina/undici/issues/258 + // Close after a HEAD request to interop with misbehaving servers + // that may send a body in the response. + + socket[kReset] = true + } + + if (upgrade || method === 'CONNECT') { + // On CONNECT or upgrade, block pipeline from dispatching further + // requests on this connection. + + socket[kReset] = true + } + + if (reset != null) { + socket[kReset] = reset + } + + if (client[kMaxRequests] && socket[kCounter]++ >= client[kMaxRequests]) { + socket[kReset] = true + } + + if (blocking) { + socket[kBlocking] = true + } + + let header = `${method} ${path} HTTP/1.1\r\n` + + if (typeof host === 'string') { + header += `host: ${host}\r\n` + } else { + header += client[kHostHeader] + } + + if (upgrade) { + header += `connection: upgrade\r\nupgrade: ${upgrade}\r\n` + } else if (client[kPipelining] && !socket[kReset]) { + header += 'connection: keep-alive\r\n' + } else { + header += 'connection: close\r\n' + } + + if (headers) { + header += headers + } + + if (channels.sendHeaders.hasSubscribers) { + channels.sendHeaders.publish({ request, headers: header, socket }) + } + + /* istanbul ignore else: assertion */ + if (!body || bodyLength === 0) { + if (contentLength === 0) { + socket.write(`${header}content-length: 0\r\n\r\n`, 'latin1') + } else { + assert(contentLength === null, 'no body must not have content length') + socket.write(`${header}\r\n`, 'latin1') + } + request.onRequestSent() + } else if (util.isBuffer(body)) { + assert(contentLength === body.byteLength, 'buffer body must have content length') + + socket.cork() + socket.write(`${header}content-length: ${contentLength}\r\n\r\n`, 'latin1') + socket.write(body) + socket.uncork() + request.onBodySent(body) + request.onRequestSent() + if (!expectsPayload) { + socket[kReset] = true + } + } else if (util.isBlobLike(body)) { + if (typeof body.stream === 'function') { + writeIterable({ body: body.stream(), client, request, socket, contentLength, header, expectsPayload }) + } else { + writeBlob({ body, client, request, socket, contentLength, header, expectsPayload }) + } + } else if (util.isStream(body)) { + writeStream({ body, client, request, socket, contentLength, header, expectsPayload }) + } else if (util.isIterable(body)) { + writeIterable({ body, client, request, socket, contentLength, header, expectsPayload }) + } else { + assert(false) + } + + return true +} + +function writeH2 (client, session, request) { + const { body, method, path, host, upgrade, expectContinue, signal, headers: reqHeaders } = request + + let headers + if (typeof reqHeaders === 'string') headers = Request[kHTTP2CopyHeaders](reqHeaders.trim()) + else headers = reqHeaders + + if (upgrade) { + errorRequest(client, request, new Error('Upgrade not supported for H2')) + return false + } + + try { + // TODO(HTTP/2): Should we call onConnect immediately or on stream ready event? + request.onConnect((err) => { + if (request.aborted || request.completed) { + return + } + + errorRequest(client, request, err || new RequestAbortedError()) + }) + } catch (err) { + errorRequest(client, request, err) + } + + if (request.aborted) { + return false + } + + /** @type {import('node:http2').ClientHttp2Stream} */ + let stream + const h2State = client[kHTTP2SessionState] + + headers[HTTP2_HEADER_AUTHORITY] = host || client[kHost] + headers[HTTP2_HEADER_METHOD] = method + + if (method === 'CONNECT') { + session.ref() + // we are already connected, streams are pending, first request + // will create a new stream. We trigger a request to create the stream and wait until + // `ready` event is triggered + // We disabled endStream to allow the user to write to the stream + stream = session.request(headers, { endStream: false, signal }) + + if (stream.id && !stream.pending) { + request.onUpgrade(null, null, stream) + ++h2State.openStreams + } else { + stream.once('ready', () => { + request.onUpgrade(null, null, stream) + ++h2State.openStreams + }) + } + + stream.once('close', () => { + h2State.openStreams -= 1 + // TODO(HTTP/2): unref only if current streams count is 0 + if (h2State.openStreams === 0) session.unref() + }) + + return true + } + + // https://tools.ietf.org/html/rfc7540#section-8.3 + // :path and :scheme headers must be omited when sending CONNECT + + headers[HTTP2_HEADER_PATH] = path + headers[HTTP2_HEADER_SCHEME] = 'https' + + // https://tools.ietf.org/html/rfc7231#section-4.3.1 + // https://tools.ietf.org/html/rfc7231#section-4.3.2 + // https://tools.ietf.org/html/rfc7231#section-4.3.5 + + // Sending a payload body on a request that does not + // expect it can cause undefined behavior on some + // servers and corrupt connection state. Do not + // re-use the connection for further requests. + + const expectsPayload = ( + method === 'PUT' || + method === 'POST' || + method === 'PATCH' + ) + + if (body && typeof body.read === 'function') { + // Try to read EOF in order to get length. + body.read(0) + } + + let contentLength = util.bodyLength(body) + + if (contentLength == null) { + contentLength = request.contentLength + } + + if (contentLength === 0 || !expectsPayload) { + // https://tools.ietf.org/html/rfc7230#section-3.3.2 + // A user agent SHOULD NOT send a Content-Length header field when + // the request message does not contain a payload body and the method + // semantics do not anticipate such a body. + + contentLength = null + } + + // https://github.com/nodejs/undici/issues/2046 + // A user agent may send a Content-Length header with 0 value, this should be allowed. + if (shouldSendContentLength(method) && contentLength > 0 && request.contentLength != null && request.contentLength !== contentLength) { + if (client[kStrictContentLength]) { + errorRequest(client, request, new RequestContentLengthMismatchError()) + return false + } + + process.emitWarning(new RequestContentLengthMismatchError()) + } + + if (contentLength != null) { + assert(body, 'no body must not have content length') + headers[HTTP2_HEADER_CONTENT_LENGTH] = `${contentLength}` + } + + session.ref() + + const shouldEndStream = method === 'GET' || method === 'HEAD' + if (expectContinue) { + headers[HTTP2_HEADER_EXPECT] = '100-continue' + stream = session.request(headers, { endStream: shouldEndStream, signal }) + + stream.once('continue', writeBodyH2) + } else { + stream = session.request(headers, { + endStream: shouldEndStream, + signal + }) + writeBodyH2() + } + + // Increment counter as we have new several streams open + ++h2State.openStreams + + stream.once('response', headers => { + const { [HTTP2_HEADER_STATUS]: statusCode, ...realHeaders } = headers + + if (request.onHeaders(Number(statusCode), realHeaders, stream.resume.bind(stream), '') === false) { + stream.pause() + } + }) + + stream.once('end', () => { + request.onComplete([]) + }) + + stream.on('data', (chunk) => { + if (request.onData(chunk) === false) { + stream.pause() + } + }) + + stream.once('close', () => { + h2State.openStreams -= 1 + // TODO(HTTP/2): unref only if current streams count is 0 + if (h2State.openStreams === 0) { + session.unref() + } + }) + + stream.once('error', function (err) { + if (client[kHTTP2Session] && !client[kHTTP2Session].destroyed && !this.closed && !this.destroyed) { + h2State.streams -= 1 + util.destroy(stream, err) + } + }) + + stream.once('frameError', (type, code) => { + const err = new InformationalError(`HTTP/2: "frameError" received - type ${type}, code ${code}`) + errorRequest(client, request, err) + + if (client[kHTTP2Session] && !client[kHTTP2Session].destroyed && !this.closed && !this.destroyed) { + h2State.streams -= 1 + util.destroy(stream, err) + } + }) + + // stream.on('aborted', () => { + // // TODO(HTTP/2): Support aborted + // }) + + // stream.on('timeout', () => { + // // TODO(HTTP/2): Support timeout + // }) + + // stream.on('push', headers => { + // // TODO(HTTP/2): Suppor push + // }) + + // stream.on('trailers', headers => { + // // TODO(HTTP/2): Support trailers + // }) + + return true + + function writeBodyH2 () { + /* istanbul ignore else: assertion */ + if (!body) { + request.onRequestSent() + } else if (util.isBuffer(body)) { + assert(contentLength === body.byteLength, 'buffer body must have content length') + stream.cork() + stream.write(body) + stream.uncork() + stream.end() + request.onBodySent(body) + request.onRequestSent() + } else if (util.isBlobLike(body)) { + if (typeof body.stream === 'function') { + writeIterable({ + client, + request, + contentLength, + h2stream: stream, + expectsPayload, + body: body.stream(), + socket: client[kSocket], + header: '' + }) + } else { + writeBlob({ + body, + client, + request, + contentLength, + expectsPayload, + h2stream: stream, + header: '', + socket: client[kSocket] + }) + } + } else if (util.isStream(body)) { + writeStream({ + body, + client, + request, + contentLength, + expectsPayload, + socket: client[kSocket], + h2stream: stream, + header: '' + }) + } else if (util.isIterable(body)) { + writeIterable({ + body, + client, + request, + contentLength, + expectsPayload, + header: '', + h2stream: stream, + socket: client[kSocket] + }) + } else { + assert(false) + } + } +} + +function writeStream ({ h2stream, body, client, request, socket, contentLength, header, expectsPayload }) { + assert(contentLength !== 0 || client[kRunning] === 0, 'stream body cannot be pipelined') + + if (client[kHTTPConnVersion] === 'h2') { + // For HTTP/2, is enough to pipe the stream + const pipe = pipeline( + body, + h2stream, + (err) => { + if (err) { + util.destroy(body, err) + util.destroy(h2stream, err) + } else { + request.onRequestSent() + } + } + ) + + pipe.on('data', onPipeData) + pipe.once('end', () => { + pipe.removeListener('data', onPipeData) + util.destroy(pipe) + }) + + function onPipeData (chunk) { + request.onBodySent(chunk) + } + + return + } + + let finished = false + + const writer = new AsyncWriter({ socket, request, contentLength, client, expectsPayload, header }) + + const onData = function (chunk) { + if (finished) { + return + } + + try { + if (!writer.write(chunk) && this.pause) { + this.pause() + } + } catch (err) { + util.destroy(this, err) + } + } + const onDrain = function () { + if (finished) { + return + } + + if (body.resume) { + body.resume() + } + } + const onAbort = function () { + if (finished) { + return + } + const err = new RequestAbortedError() + queueMicrotask(() => onFinished(err)) + } + const onFinished = function (err) { + if (finished) { + return + } + + finished = true + + assert(socket.destroyed || (socket[kWriting] && client[kRunning] <= 1)) + + socket + .off('drain', onDrain) + .off('error', onFinished) + + body + .removeListener('data', onData) + .removeListener('end', onFinished) + .removeListener('error', onFinished) + .removeListener('close', onAbort) + + if (!err) { + try { + writer.end() + } catch (er) { + err = er + } + } + + writer.destroy(err) + + if (err && (err.code !== 'UND_ERR_INFO' || err.message !== 'reset')) { + util.destroy(body, err) + } else { + util.destroy(body) + } + } + + body + .on('data', onData) + .on('end', onFinished) + .on('error', onFinished) + .on('close', onAbort) + + if (body.resume) { + body.resume() + } + + socket + .on('drain', onDrain) + .on('error', onFinished) +} + +async function writeBlob ({ h2stream, body, client, request, socket, contentLength, header, expectsPayload }) { + assert(contentLength === body.size, 'blob body must have content length') + + const isH2 = client[kHTTPConnVersion] === 'h2' + try { + if (contentLength != null && contentLength !== body.size) { + throw new RequestContentLengthMismatchError() + } + + const buffer = Buffer.from(await body.arrayBuffer()) + + if (isH2) { + h2stream.cork() + h2stream.write(buffer) + h2stream.uncork() + } else { + socket.cork() + socket.write(`${header}content-length: ${contentLength}\r\n\r\n`, 'latin1') + socket.write(buffer) + socket.uncork() + } + + request.onBodySent(buffer) + request.onRequestSent() + + if (!expectsPayload) { + socket[kReset] = true + } + + resume(client) + } catch (err) { + util.destroy(isH2 ? h2stream : socket, err) + } +} + +async function writeIterable ({ h2stream, body, client, request, socket, contentLength, header, expectsPayload }) { + assert(contentLength !== 0 || client[kRunning] === 0, 'iterator body cannot be pipelined') + + let callback = null + function onDrain () { + if (callback) { + const cb = callback + callback = null + cb() + } + } + + const waitForDrain = () => new Promise((resolve, reject) => { + assert(callback === null) + + if (socket[kError]) { + reject(socket[kError]) + } else { + callback = resolve + } + }) + + if (client[kHTTPConnVersion] === 'h2') { + h2stream + .on('close', onDrain) + .on('drain', onDrain) + + try { + // It's up to the user to somehow abort the async iterable. + for await (const chunk of body) { + if (socket[kError]) { + throw socket[kError] + } + + const res = h2stream.write(chunk) + request.onBodySent(chunk) + if (!res) { + await waitForDrain() + } + } + } catch (err) { + h2stream.destroy(err) + } finally { + request.onRequestSent() + h2stream.end() + h2stream + .off('close', onDrain) + .off('drain', onDrain) + } + + return + } + + socket + .on('close', onDrain) + .on('drain', onDrain) + + const writer = new AsyncWriter({ socket, request, contentLength, client, expectsPayload, header }) + try { + // It's up to the user to somehow abort the async iterable. + for await (const chunk of body) { + if (socket[kError]) { + throw socket[kError] + } + + if (!writer.write(chunk)) { + await waitForDrain() + } + } + + writer.end() + } catch (err) { + writer.destroy(err) + } finally { + socket + .off('close', onDrain) + .off('drain', onDrain) + } +} + +class AsyncWriter { + constructor ({ socket, request, contentLength, client, expectsPayload, header }) { + this.socket = socket + this.request = request + this.contentLength = contentLength + this.client = client + this.bytesWritten = 0 + this.expectsPayload = expectsPayload + this.header = header + + socket[kWriting] = true + } + + write (chunk) { + const { socket, request, contentLength, client, bytesWritten, expectsPayload, header } = this + + if (socket[kError]) { + throw socket[kError] + } + + if (socket.destroyed) { + return false + } + + const len = Buffer.byteLength(chunk) + if (!len) { + return true + } + + // We should defer writing chunks. + if (contentLength !== null && bytesWritten + len > contentLength) { + if (client[kStrictContentLength]) { + throw new RequestContentLengthMismatchError() + } + + process.emitWarning(new RequestContentLengthMismatchError()) + } + + socket.cork() + + if (bytesWritten === 0) { + if (!expectsPayload) { + socket[kReset] = true + } + + if (contentLength === null) { + socket.write(`${header}transfer-encoding: chunked\r\n`, 'latin1') + } else { + socket.write(`${header}content-length: ${contentLength}\r\n\r\n`, 'latin1') + } + } + + if (contentLength === null) { + socket.write(`\r\n${len.toString(16)}\r\n`, 'latin1') + } + + this.bytesWritten += len + + const ret = socket.write(chunk) + + socket.uncork() + + request.onBodySent(chunk) + + if (!ret) { + if (socket[kParser].timeout && socket[kParser].timeoutType === TIMEOUT_HEADERS) { + // istanbul ignore else: only for jest + if (socket[kParser].timeout.refresh) { + socket[kParser].timeout.refresh() + } + } + } + + return ret + } + + end () { + const { socket, contentLength, client, bytesWritten, expectsPayload, header, request } = this + request.onRequestSent() + + socket[kWriting] = false + + if (socket[kError]) { + throw socket[kError] + } + + if (socket.destroyed) { + return + } + + if (bytesWritten === 0) { + if (expectsPayload) { + // https://tools.ietf.org/html/rfc7230#section-3.3.2 + // A user agent SHOULD send a Content-Length in a request message when + // no Transfer-Encoding is sent and the request method defines a meaning + // for an enclosed payload body. + + socket.write(`${header}content-length: 0\r\n\r\n`, 'latin1') + } else { + socket.write(`${header}\r\n`, 'latin1') + } + } else if (contentLength === null) { + socket.write('\r\n0\r\n\r\n', 'latin1') + } + + if (contentLength !== null && bytesWritten !== contentLength) { + if (client[kStrictContentLength]) { + throw new RequestContentLengthMismatchError() + } else { + process.emitWarning(new RequestContentLengthMismatchError()) + } + } + + if (socket[kParser].timeout && socket[kParser].timeoutType === TIMEOUT_HEADERS) { + // istanbul ignore else: only for jest + if (socket[kParser].timeout.refresh) { + socket[kParser].timeout.refresh() + } + } + + resume(client) + } + + destroy (err) { + const { socket, client } = this + + socket[kWriting] = false + + if (err) { + assert(client[kRunning] <= 1, 'pipeline should only contain this request') + util.destroy(socket, err) + } + } +} + +function errorRequest (client, request, err) { + try { + request.onError(err) + assert(request.aborted) + } catch (err) { + client.emit('error', err) + } +} + +module.exports = Client + + +/***/ }), + +/***/ 231: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +/* istanbul ignore file: only for Node 12 */ + +const { kConnected, kSize } = __nccwpck_require__(9440) + +class CompatWeakRef { + constructor (value) { + this.value = value + } + + deref () { + return this.value[kConnected] === 0 && this.value[kSize] === 0 + ? undefined + : this.value + } +} + +class CompatFinalizer { + constructor (finalizer) { + this.finalizer = finalizer + } + + register (dispatcher, key) { + if (dispatcher.on) { + dispatcher.on('disconnect', () => { + if (dispatcher[kConnected] === 0 && dispatcher[kSize] === 0) { + this.finalizer(key) + } + }) + } + } +} + +module.exports = function () { + // FIXME: remove workaround when the Node bug is fixed + // https://github.com/nodejs/node/issues/49344#issuecomment-1741776308 + if (process.env.NODE_V8_COVERAGE) { + return { + WeakRef: CompatWeakRef, + FinalizationRegistry: CompatFinalizer + } + } + return { + WeakRef: global.WeakRef || CompatWeakRef, + FinalizationRegistry: global.FinalizationRegistry || CompatFinalizer + } +} + + +/***/ }), + +/***/ 5406: +/***/ ((module) => { + +"use strict"; + + +// https://wicg.github.io/cookie-store/#cookie-maximum-attribute-value-size +const maxAttributeValueSize = 1024 + +// https://wicg.github.io/cookie-store/#cookie-maximum-name-value-pair-size +const maxNameValuePairSize = 4096 + +module.exports = { + maxAttributeValueSize, + maxNameValuePairSize +} + + +/***/ }), + +/***/ 7484: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { parseSetCookie } = __nccwpck_require__(8644) +const { stringify, getHeadersList } = __nccwpck_require__(1035) +const { webidl } = __nccwpck_require__(1537) +const { Headers } = __nccwpck_require__(7689) + +/** + * @typedef {Object} Cookie + * @property {string} name + * @property {string} value + * @property {Date|number|undefined} expires + * @property {number|undefined} maxAge + * @property {string|undefined} domain + * @property {string|undefined} path + * @property {boolean|undefined} secure + * @property {boolean|undefined} httpOnly + * @property {'Strict'|'Lax'|'None'} sameSite + * @property {string[]} unparsed + */ + +/** + * @param {Headers} headers + * @returns {Record} + */ +function getCookies (headers) { + webidl.argumentLengthCheck(arguments, 1, { header: 'getCookies' }) + + webidl.brandCheck(headers, Headers, { strict: false }) + + const cookie = headers.get('cookie') + const out = {} + + if (!cookie) { + return out + } + + for (const piece of cookie.split(';')) { + const [name, ...value] = piece.split('=') + + out[name.trim()] = value.join('=') + } + + return out +} + +/** + * @param {Headers} headers + * @param {string} name + * @param {{ path?: string, domain?: string }|undefined} attributes + * @returns {void} + */ +function deleteCookie (headers, name, attributes) { + webidl.argumentLengthCheck(arguments, 2, { header: 'deleteCookie' }) + + webidl.brandCheck(headers, Headers, { strict: false }) + + name = webidl.converters.DOMString(name) + attributes = webidl.converters.DeleteCookieAttributes(attributes) + + // Matches behavior of + // https://github.com/denoland/deno_std/blob/63827b16330b82489a04614027c33b7904e08be5/http/cookie.ts#L278 + setCookie(headers, { + name, + value: '', + expires: new Date(0), + ...attributes + }) +} + +/** + * @param {Headers} headers + * @returns {Cookie[]} + */ +function getSetCookies (headers) { + webidl.argumentLengthCheck(arguments, 1, { header: 'getSetCookies' }) + + webidl.brandCheck(headers, Headers, { strict: false }) + + const cookies = getHeadersList(headers).cookies + + if (!cookies) { + return [] + } + + // In older versions of undici, cookies is a list of name:value. + return cookies.map((pair) => parseSetCookie(Array.isArray(pair) ? pair[1] : pair)) +} + +/** + * @param {Headers} headers + * @param {Cookie} cookie + * @returns {void} + */ +function setCookie (headers, cookie) { + webidl.argumentLengthCheck(arguments, 2, { header: 'setCookie' }) + + webidl.brandCheck(headers, Headers, { strict: false }) + + cookie = webidl.converters.Cookie(cookie) + + const str = stringify(cookie) + + if (str) { + headers.append('Set-Cookie', stringify(cookie)) + } +} + +webidl.converters.DeleteCookieAttributes = webidl.dictionaryConverter([ + { + converter: webidl.nullableConverter(webidl.converters.DOMString), + key: 'path', + defaultValue: null + }, + { + converter: webidl.nullableConverter(webidl.converters.DOMString), + key: 'domain', + defaultValue: null + } +]) + +webidl.converters.Cookie = webidl.dictionaryConverter([ + { + converter: webidl.converters.DOMString, + key: 'name' + }, + { + converter: webidl.converters.DOMString, + key: 'value' + }, + { + converter: webidl.nullableConverter((value) => { + if (typeof value === 'number') { + return webidl.converters['unsigned long long'](value) + } + + return new Date(value) + }), + key: 'expires', + defaultValue: null + }, + { + converter: webidl.nullableConverter(webidl.converters['long long']), + key: 'maxAge', + defaultValue: null + }, + { + converter: webidl.nullableConverter(webidl.converters.DOMString), + key: 'domain', + defaultValue: null + }, + { + converter: webidl.nullableConverter(webidl.converters.DOMString), + key: 'path', + defaultValue: null + }, + { + converter: webidl.nullableConverter(webidl.converters.boolean), + key: 'secure', + defaultValue: null + }, + { + converter: webidl.nullableConverter(webidl.converters.boolean), + key: 'httpOnly', + defaultValue: null + }, + { + converter: webidl.converters.USVString, + key: 'sameSite', + allowedValues: ['Strict', 'Lax', 'None'] + }, + { + converter: webidl.sequenceConverter(webidl.converters.DOMString), + key: 'unparsed', + defaultValue: [] + } +]) + +module.exports = { + getCookies, + deleteCookie, + getSetCookies, + setCookie +} + + +/***/ }), + +/***/ 8644: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { maxNameValuePairSize, maxAttributeValueSize } = __nccwpck_require__(5406) +const { isCTLExcludingHtab } = __nccwpck_require__(1035) +const { collectASequenceOfCodePointsFast } = __nccwpck_require__(2791) +const assert = __nccwpck_require__(9491) + +/** + * @description Parses the field-value attributes of a set-cookie header string. + * @see https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4 + * @param {string} header + * @returns if the header is invalid, null will be returned + */ +function parseSetCookie (header) { + // 1. If the set-cookie-string contains a %x00-08 / %x0A-1F / %x7F + // character (CTL characters excluding HTAB): Abort these steps and + // ignore the set-cookie-string entirely. + if (isCTLExcludingHtab(header)) { + return null + } + + let nameValuePair = '' + let unparsedAttributes = '' + let name = '' + let value = '' + + // 2. If the set-cookie-string contains a %x3B (";") character: + if (header.includes(';')) { + // 1. The name-value-pair string consists of the characters up to, + // but not including, the first %x3B (";"), and the unparsed- + // attributes consist of the remainder of the set-cookie-string + // (including the %x3B (";") in question). + const position = { position: 0 } + + nameValuePair = collectASequenceOfCodePointsFast(';', header, position) + unparsedAttributes = header.slice(position.position) + } else { + // Otherwise: + + // 1. The name-value-pair string consists of all the characters + // contained in the set-cookie-string, and the unparsed- + // attributes is the empty string. + nameValuePair = header + } + + // 3. If the name-value-pair string lacks a %x3D ("=") character, then + // the name string is empty, and the value string is the value of + // name-value-pair. + if (!nameValuePair.includes('=')) { + value = nameValuePair + } else { + // Otherwise, the name string consists of the characters up to, but + // not including, the first %x3D ("=") character, and the (possibly + // empty) value string consists of the characters after the first + // %x3D ("=") character. + const position = { position: 0 } + name = collectASequenceOfCodePointsFast( + '=', + nameValuePair, + position + ) + value = nameValuePair.slice(position.position + 1) + } + + // 4. Remove any leading or trailing WSP characters from the name + // string and the value string. + name = name.trim() + value = value.trim() + + // 5. If the sum of the lengths of the name string and the value string + // is more than 4096 octets, abort these steps and ignore the set- + // cookie-string entirely. + if (name.length + value.length > maxNameValuePairSize) { + return null + } + + // 6. The cookie-name is the name string, and the cookie-value is the + // value string. + return { + name, value, ...parseUnparsedAttributes(unparsedAttributes) + } +} + +/** + * Parses the remaining attributes of a set-cookie header + * @see https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4 + * @param {string} unparsedAttributes + * @param {[Object.]={}} cookieAttributeList + */ +function parseUnparsedAttributes (unparsedAttributes, cookieAttributeList = {}) { + // 1. If the unparsed-attributes string is empty, skip the rest of + // these steps. + if (unparsedAttributes.length === 0) { + return cookieAttributeList + } + + // 2. Discard the first character of the unparsed-attributes (which + // will be a %x3B (";") character). + assert(unparsedAttributes[0] === ';') + unparsedAttributes = unparsedAttributes.slice(1) + + let cookieAv = '' + + // 3. If the remaining unparsed-attributes contains a %x3B (";") + // character: + if (unparsedAttributes.includes(';')) { + // 1. Consume the characters of the unparsed-attributes up to, but + // not including, the first %x3B (";") character. + cookieAv = collectASequenceOfCodePointsFast( + ';', + unparsedAttributes, + { position: 0 } + ) + unparsedAttributes = unparsedAttributes.slice(cookieAv.length) + } else { + // Otherwise: + + // 1. Consume the remainder of the unparsed-attributes. + cookieAv = unparsedAttributes + unparsedAttributes = '' + } + + // Let the cookie-av string be the characters consumed in this step. + + let attributeName = '' + let attributeValue = '' + + // 4. If the cookie-av string contains a %x3D ("=") character: + if (cookieAv.includes('=')) { + // 1. The (possibly empty) attribute-name string consists of the + // characters up to, but not including, the first %x3D ("=") + // character, and the (possibly empty) attribute-value string + // consists of the characters after the first %x3D ("=") + // character. + const position = { position: 0 } + + attributeName = collectASequenceOfCodePointsFast( + '=', + cookieAv, + position + ) + attributeValue = cookieAv.slice(position.position + 1) + } else { + // Otherwise: + + // 1. The attribute-name string consists of the entire cookie-av + // string, and the attribute-value string is empty. + attributeName = cookieAv + } + + // 5. Remove any leading or trailing WSP characters from the attribute- + // name string and the attribute-value string. + attributeName = attributeName.trim() + attributeValue = attributeValue.trim() + + // 6. If the attribute-value is longer than 1024 octets, ignore the + // cookie-av string and return to Step 1 of this algorithm. + if (attributeValue.length > maxAttributeValueSize) { + return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList) + } + + // 7. Process the attribute-name and attribute-value according to the + // requirements in the following subsections. (Notice that + // attributes with unrecognized attribute-names are ignored.) + const attributeNameLowercase = attributeName.toLowerCase() + + // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.1 + // If the attribute-name case-insensitively matches the string + // "Expires", the user agent MUST process the cookie-av as follows. + if (attributeNameLowercase === 'expires') { + // 1. Let the expiry-time be the result of parsing the attribute-value + // as cookie-date (see Section 5.1.1). + const expiryTime = new Date(attributeValue) + + // 2. If the attribute-value failed to parse as a cookie date, ignore + // the cookie-av. + + cookieAttributeList.expires = expiryTime + } else if (attributeNameLowercase === 'max-age') { + // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.2 + // If the attribute-name case-insensitively matches the string "Max- + // Age", the user agent MUST process the cookie-av as follows. + + // 1. If the first character of the attribute-value is not a DIGIT or a + // "-" character, ignore the cookie-av. + const charCode = attributeValue.charCodeAt(0) + + if ((charCode < 48 || charCode > 57) && attributeValue[0] !== '-') { + return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList) + } + + // 2. If the remainder of attribute-value contains a non-DIGIT + // character, ignore the cookie-av. + if (!/^\d+$/.test(attributeValue)) { + return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList) + } + + // 3. Let delta-seconds be the attribute-value converted to an integer. + const deltaSeconds = Number(attributeValue) + + // 4. Let cookie-age-limit be the maximum age of the cookie (which + // SHOULD be 400 days or less, see Section 4.1.2.2). + + // 5. Set delta-seconds to the smaller of its present value and cookie- + // age-limit. + // deltaSeconds = Math.min(deltaSeconds * 1000, maxExpiresMs) + + // 6. If delta-seconds is less than or equal to zero (0), let expiry- + // time be the earliest representable date and time. Otherwise, let + // the expiry-time be the current date and time plus delta-seconds + // seconds. + // const expiryTime = deltaSeconds <= 0 ? Date.now() : Date.now() + deltaSeconds + + // 7. Append an attribute to the cookie-attribute-list with an + // attribute-name of Max-Age and an attribute-value of expiry-time. + cookieAttributeList.maxAge = deltaSeconds + } else if (attributeNameLowercase === 'domain') { + // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.3 + // If the attribute-name case-insensitively matches the string "Domain", + // the user agent MUST process the cookie-av as follows. + + // 1. Let cookie-domain be the attribute-value. + let cookieDomain = attributeValue + + // 2. If cookie-domain starts with %x2E ("."), let cookie-domain be + // cookie-domain without its leading %x2E ("."). + if (cookieDomain[0] === '.') { + cookieDomain = cookieDomain.slice(1) + } + + // 3. Convert the cookie-domain to lower case. + cookieDomain = cookieDomain.toLowerCase() + + // 4. Append an attribute to the cookie-attribute-list with an + // attribute-name of Domain and an attribute-value of cookie-domain. + cookieAttributeList.domain = cookieDomain + } else if (attributeNameLowercase === 'path') { + // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.4 + // If the attribute-name case-insensitively matches the string "Path", + // the user agent MUST process the cookie-av as follows. + + // 1. If the attribute-value is empty or if the first character of the + // attribute-value is not %x2F ("/"): + let cookiePath = '' + if (attributeValue.length === 0 || attributeValue[0] !== '/') { + // 1. Let cookie-path be the default-path. + cookiePath = '/' + } else { + // Otherwise: + + // 1. Let cookie-path be the attribute-value. + cookiePath = attributeValue + } + + // 2. Append an attribute to the cookie-attribute-list with an + // attribute-name of Path and an attribute-value of cookie-path. + cookieAttributeList.path = cookiePath + } else if (attributeNameLowercase === 'secure') { + // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.5 + // If the attribute-name case-insensitively matches the string "Secure", + // the user agent MUST append an attribute to the cookie-attribute-list + // with an attribute-name of Secure and an empty attribute-value. + + cookieAttributeList.secure = true + } else if (attributeNameLowercase === 'httponly') { + // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.6 + // If the attribute-name case-insensitively matches the string + // "HttpOnly", the user agent MUST append an attribute to the cookie- + // attribute-list with an attribute-name of HttpOnly and an empty + // attribute-value. + + cookieAttributeList.httpOnly = true + } else if (attributeNameLowercase === 'samesite') { + // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.7 + // If the attribute-name case-insensitively matches the string + // "SameSite", the user agent MUST process the cookie-av as follows: + + // 1. Let enforcement be "Default". + let enforcement = 'Default' + + const attributeValueLowercase = attributeValue.toLowerCase() + // 2. If cookie-av's attribute-value is a case-insensitive match for + // "None", set enforcement to "None". + if (attributeValueLowercase.includes('none')) { + enforcement = 'None' + } + + // 3. If cookie-av's attribute-value is a case-insensitive match for + // "Strict", set enforcement to "Strict". + if (attributeValueLowercase.includes('strict')) { + enforcement = 'Strict' + } + + // 4. If cookie-av's attribute-value is a case-insensitive match for + // "Lax", set enforcement to "Lax". + if (attributeValueLowercase.includes('lax')) { + enforcement = 'Lax' + } + + // 5. Append an attribute to the cookie-attribute-list with an + // attribute-name of "SameSite" and an attribute-value of + // enforcement. + cookieAttributeList.sameSite = enforcement + } else { + cookieAttributeList.unparsed ??= [] + + cookieAttributeList.unparsed.push(`${attributeName}=${attributeValue}`) + } + + // 8. Return to Step 1 of this algorithm. + return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList) +} + +module.exports = { + parseSetCookie, + parseUnparsedAttributes +} + + +/***/ }), + +/***/ 1035: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const assert = __nccwpck_require__(9491) +const { kHeadersList } = __nccwpck_require__(9440) + +function isCTLExcludingHtab (value) { + if (value.length === 0) { + return false + } + + for (const char of value) { + const code = char.charCodeAt(0) + + if ( + (code >= 0x00 || code <= 0x08) || + (code >= 0x0A || code <= 0x1F) || + code === 0x7F + ) { + return false + } + } +} + +/** + CHAR = + token = 1* + separators = "(" | ")" | "<" | ">" | "@" + | "," | ";" | ":" | "\" | <"> + | "/" | "[" | "]" | "?" | "=" + | "{" | "}" | SP | HT + * @param {string} name + */ +function validateCookieName (name) { + for (const char of name) { + const code = char.charCodeAt(0) + + if ( + (code <= 0x20 || code > 0x7F) || + char === '(' || + char === ')' || + char === '>' || + char === '<' || + char === '@' || + char === ',' || + char === ';' || + char === ':' || + char === '\\' || + char === '"' || + char === '/' || + char === '[' || + char === ']' || + char === '?' || + char === '=' || + char === '{' || + char === '}' + ) { + throw new Error('Invalid cookie name') + } + } +} + +/** + cookie-value = *cookie-octet / ( DQUOTE *cookie-octet DQUOTE ) + cookie-octet = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E + ; US-ASCII characters excluding CTLs, + ; whitespace DQUOTE, comma, semicolon, + ; and backslash + * @param {string} value + */ +function validateCookieValue (value) { + for (const char of value) { + const code = char.charCodeAt(0) + + if ( + code < 0x21 || // exclude CTLs (0-31) + code === 0x22 || + code === 0x2C || + code === 0x3B || + code === 0x5C || + code > 0x7E // non-ascii + ) { + throw new Error('Invalid header value') + } + } +} + +/** + * path-value = + * @param {string} path + */ +function validateCookiePath (path) { + for (const char of path) { + const code = char.charCodeAt(0) + + if (code < 0x21 || char === ';') { + throw new Error('Invalid cookie path') + } + } +} + +/** + * I have no idea why these values aren't allowed to be honest, + * but Deno tests these. - Khafra + * @param {string} domain + */ +function validateCookieDomain (domain) { + if ( + domain.startsWith('-') || + domain.endsWith('.') || + domain.endsWith('-') + ) { + throw new Error('Invalid cookie domain') + } +} + +/** + * @see https://www.rfc-editor.org/rfc/rfc7231#section-7.1.1.1 + * @param {number|Date} date + IMF-fixdate = day-name "," SP date1 SP time-of-day SP GMT + ; fixed length/zone/capitalization subset of the format + ; see Section 3.3 of [RFC5322] + + day-name = %x4D.6F.6E ; "Mon", case-sensitive + / %x54.75.65 ; "Tue", case-sensitive + / %x57.65.64 ; "Wed", case-sensitive + / %x54.68.75 ; "Thu", case-sensitive + / %x46.72.69 ; "Fri", case-sensitive + / %x53.61.74 ; "Sat", case-sensitive + / %x53.75.6E ; "Sun", case-sensitive + date1 = day SP month SP year + ; e.g., 02 Jun 1982 + + day = 2DIGIT + month = %x4A.61.6E ; "Jan", case-sensitive + / %x46.65.62 ; "Feb", case-sensitive + / %x4D.61.72 ; "Mar", case-sensitive + / %x41.70.72 ; "Apr", case-sensitive + / %x4D.61.79 ; "May", case-sensitive + / %x4A.75.6E ; "Jun", case-sensitive + / %x4A.75.6C ; "Jul", case-sensitive + / %x41.75.67 ; "Aug", case-sensitive + / %x53.65.70 ; "Sep", case-sensitive + / %x4F.63.74 ; "Oct", case-sensitive + / %x4E.6F.76 ; "Nov", case-sensitive + / %x44.65.63 ; "Dec", case-sensitive + year = 4DIGIT + + GMT = %x47.4D.54 ; "GMT", case-sensitive + + time-of-day = hour ":" minute ":" second + ; 00:00:00 - 23:59:60 (leap second) + + hour = 2DIGIT + minute = 2DIGIT + second = 2DIGIT + */ +function toIMFDate (date) { + if (typeof date === 'number') { + date = new Date(date) + } + + const days = [ + 'Sun', 'Mon', 'Tue', 'Wed', + 'Thu', 'Fri', 'Sat' + ] + + const months = [ + 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', + 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' + ] + + const dayName = days[date.getUTCDay()] + const day = date.getUTCDate().toString().padStart(2, '0') + const month = months[date.getUTCMonth()] + const year = date.getUTCFullYear() + const hour = date.getUTCHours().toString().padStart(2, '0') + const minute = date.getUTCMinutes().toString().padStart(2, '0') + const second = date.getUTCSeconds().toString().padStart(2, '0') + + return `${dayName}, ${day} ${month} ${year} ${hour}:${minute}:${second} GMT` +} + +/** + max-age-av = "Max-Age=" non-zero-digit *DIGIT + ; In practice, both expires-av and max-age-av + ; are limited to dates representable by the + ; user agent. + * @param {number} maxAge + */ +function validateCookieMaxAge (maxAge) { + if (maxAge < 0) { + throw new Error('Invalid cookie max-age') + } +} + +/** + * @see https://www.rfc-editor.org/rfc/rfc6265#section-4.1.1 + * @param {import('./index').Cookie} cookie + */ +function stringify (cookie) { + if (cookie.name.length === 0) { + return null + } + + validateCookieName(cookie.name) + validateCookieValue(cookie.value) + + const out = [`${cookie.name}=${cookie.value}`] + + // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-cookie-prefixes-00#section-3.1 + // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-cookie-prefixes-00#section-3.2 + if (cookie.name.startsWith('__Secure-')) { + cookie.secure = true + } + + if (cookie.name.startsWith('__Host-')) { + cookie.secure = true + cookie.domain = null + cookie.path = '/' + } + + if (cookie.secure) { + out.push('Secure') + } + + if (cookie.httpOnly) { + out.push('HttpOnly') + } + + if (typeof cookie.maxAge === 'number') { + validateCookieMaxAge(cookie.maxAge) + out.push(`Max-Age=${cookie.maxAge}`) + } + + if (cookie.domain) { + validateCookieDomain(cookie.domain) + out.push(`Domain=${cookie.domain}`) + } + + if (cookie.path) { + validateCookiePath(cookie.path) + out.push(`Path=${cookie.path}`) + } + + if (cookie.expires && cookie.expires.toString() !== 'Invalid Date') { + out.push(`Expires=${toIMFDate(cookie.expires)}`) + } + + if (cookie.sameSite) { + out.push(`SameSite=${cookie.sameSite}`) + } + + for (const part of cookie.unparsed) { + if (!part.includes('=')) { + throw new Error('Invalid unparsed') + } + + const [key, ...value] = part.split('=') + + out.push(`${key.trim()}=${value.join('=')}`) + } + + return out.join('; ') +} + +let kHeadersListNode + +function getHeadersList (headers) { + if (headers[kHeadersList]) { + return headers[kHeadersList] + } + + if (!kHeadersListNode) { + kHeadersListNode = Object.getOwnPropertySymbols(headers).find( + (symbol) => symbol.description === 'headers list' + ) + + assert(kHeadersListNode, 'Headers cannot be parsed') + } + + const headersList = headers[kHeadersListNode] + assert(headersList) + + return headersList +} + +module.exports = { + isCTLExcludingHtab, + stringify, + getHeadersList +} + + +/***/ }), + +/***/ 7530: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const net = __nccwpck_require__(1808) +const assert = __nccwpck_require__(9491) +const util = __nccwpck_require__(9522) +const { InvalidArgumentError, ConnectTimeoutError } = __nccwpck_require__(721) + +let tls // include tls conditionally since it is not always available + +// TODO: session re-use does not wait for the first +// connection to resolve the session and might therefore +// resolve the same servername multiple times even when +// re-use is enabled. + +let SessionCache +// FIXME: remove workaround when the Node bug is fixed +// https://github.com/nodejs/node/issues/49344#issuecomment-1741776308 +if (global.FinalizationRegistry && !process.env.NODE_V8_COVERAGE) { + SessionCache = class WeakSessionCache { + constructor (maxCachedSessions) { + this._maxCachedSessions = maxCachedSessions + this._sessionCache = new Map() + this._sessionRegistry = new global.FinalizationRegistry((key) => { + if (this._sessionCache.size < this._maxCachedSessions) { + return + } + + const ref = this._sessionCache.get(key) + if (ref !== undefined && ref.deref() === undefined) { + this._sessionCache.delete(key) + } + }) + } + + get (sessionKey) { + const ref = this._sessionCache.get(sessionKey) + return ref ? ref.deref() : null + } + + set (sessionKey, session) { + if (this._maxCachedSessions === 0) { + return + } + + this._sessionCache.set(sessionKey, new WeakRef(session)) + this._sessionRegistry.register(session, sessionKey) + } + } +} else { + SessionCache = class SimpleSessionCache { + constructor (maxCachedSessions) { + this._maxCachedSessions = maxCachedSessions + this._sessionCache = new Map() + } + + get (sessionKey) { + return this._sessionCache.get(sessionKey) + } + + set (sessionKey, session) { + if (this._maxCachedSessions === 0) { + return + } + + if (this._sessionCache.size >= this._maxCachedSessions) { + // remove the oldest session + const { value: oldestKey } = this._sessionCache.keys().next() + this._sessionCache.delete(oldestKey) + } + + this._sessionCache.set(sessionKey, session) + } + } +} + +function buildConnector ({ allowH2, maxCachedSessions, socketPath, timeout, ...opts }) { + if (maxCachedSessions != null && (!Number.isInteger(maxCachedSessions) || maxCachedSessions < 0)) { + throw new InvalidArgumentError('maxCachedSessions must be a positive integer or zero') + } + + const options = { path: socketPath, ...opts } + const sessionCache = new SessionCache(maxCachedSessions == null ? 100 : maxCachedSessions) + timeout = timeout == null ? 10e3 : timeout + allowH2 = allowH2 != null ? allowH2 : false + return function connect ({ hostname, host, protocol, port, servername, localAddress, httpSocket }, callback) { + let socket + if (protocol === 'https:') { + if (!tls) { + tls = __nccwpck_require__(4404) + } + servername = servername || options.servername || util.getServerName(host) || null + + const sessionKey = servername || hostname + const session = sessionCache.get(sessionKey) || null + + assert(sessionKey) + + socket = tls.connect({ + highWaterMark: 16384, // TLS in node can't have bigger HWM anyway... + ...options, + servername, + session, + localAddress, + // TODO(HTTP/2): Add support for h2c + ALPNProtocols: allowH2 ? ['http/1.1', 'h2'] : ['http/1.1'], + socket: httpSocket, // upgrade socket connection + port: port || 443, + host: hostname + }) + + socket + .on('session', function (session) { + // TODO (fix): Can a session become invalid once established? Don't think so? + sessionCache.set(sessionKey, session) + }) + } else { + assert(!httpSocket, 'httpSocket can only be sent on TLS update') + socket = net.connect({ + highWaterMark: 64 * 1024, // Same as nodejs fs streams. + ...options, + localAddress, + port: port || 80, + host: hostname + }) + } + + // Set TCP keep alive options on the socket here instead of in connect() for the case of assigning the socket + if (options.keepAlive == null || options.keepAlive) { + const keepAliveInitialDelay = options.keepAliveInitialDelay === undefined ? 60e3 : options.keepAliveInitialDelay + socket.setKeepAlive(true, keepAliveInitialDelay) + } + + const cancelTimeout = setupTimeout(() => onConnectTimeout(socket), timeout) + + socket + .setNoDelay(true) + .once(protocol === 'https:' ? 'secureConnect' : 'connect', function () { + cancelTimeout() + + if (callback) { + const cb = callback + callback = null + cb(null, this) + } + }) + .on('error', function (err) { + cancelTimeout() + + if (callback) { + const cb = callback + callback = null + cb(err) + } + }) + + return socket + } +} + +function setupTimeout (onConnectTimeout, timeout) { + if (!timeout) { + return () => {} + } + + let s1 = null + let s2 = null + const timeoutId = setTimeout(() => { + // setImmediate is added to make sure that we priotorise socket error events over timeouts + s1 = setImmediate(() => { + if (process.platform === 'win32') { + // Windows needs an extra setImmediate probably due to implementation differences in the socket logic + s2 = setImmediate(() => onConnectTimeout()) + } else { + onConnectTimeout() + } + }) + }, timeout) + return () => { + clearTimeout(timeoutId) + clearImmediate(s1) + clearImmediate(s2) + } +} + +function onConnectTimeout (socket) { + util.destroy(socket, new ConnectTimeoutError()) +} + +module.exports = buildConnector + + +/***/ }), + +/***/ 721: +/***/ ((module) => { + +"use strict"; + + +class UndiciError extends Error { + constructor (message) { + super(message) + this.name = 'UndiciError' + this.code = 'UND_ERR' + } +} + +class ConnectTimeoutError extends UndiciError { + constructor (message) { + super(message) + Error.captureStackTrace(this, ConnectTimeoutError) + this.name = 'ConnectTimeoutError' + this.message = message || 'Connect Timeout Error' + this.code = 'UND_ERR_CONNECT_TIMEOUT' + } +} + +class HeadersTimeoutError extends UndiciError { + constructor (message) { + super(message) + Error.captureStackTrace(this, HeadersTimeoutError) + this.name = 'HeadersTimeoutError' + this.message = message || 'Headers Timeout Error' + this.code = 'UND_ERR_HEADERS_TIMEOUT' + } +} + +class HeadersOverflowError extends UndiciError { + constructor (message) { + super(message) + Error.captureStackTrace(this, HeadersOverflowError) + this.name = 'HeadersOverflowError' + this.message = message || 'Headers Overflow Error' + this.code = 'UND_ERR_HEADERS_OVERFLOW' + } +} + +class BodyTimeoutError extends UndiciError { + constructor (message) { + super(message) + Error.captureStackTrace(this, BodyTimeoutError) + this.name = 'BodyTimeoutError' + this.message = message || 'Body Timeout Error' + this.code = 'UND_ERR_BODY_TIMEOUT' + } +} + +class ResponseStatusCodeError extends UndiciError { + constructor (message, statusCode, headers, body) { + super(message) + Error.captureStackTrace(this, ResponseStatusCodeError) + this.name = 'ResponseStatusCodeError' + this.message = message || 'Response Status Code Error' + this.code = 'UND_ERR_RESPONSE_STATUS_CODE' + this.body = body + this.status = statusCode + this.statusCode = statusCode + this.headers = headers + } +} + +class InvalidArgumentError extends UndiciError { + constructor (message) { + super(message) + Error.captureStackTrace(this, InvalidArgumentError) + this.name = 'InvalidArgumentError' + this.message = message || 'Invalid Argument Error' + this.code = 'UND_ERR_INVALID_ARG' + } +} + +class InvalidReturnValueError extends UndiciError { + constructor (message) { + super(message) + Error.captureStackTrace(this, InvalidReturnValueError) + this.name = 'InvalidReturnValueError' + this.message = message || 'Invalid Return Value Error' + this.code = 'UND_ERR_INVALID_RETURN_VALUE' + } +} + +class RequestAbortedError extends UndiciError { + constructor (message) { + super(message) + Error.captureStackTrace(this, RequestAbortedError) + this.name = 'AbortError' + this.message = message || 'Request aborted' + this.code = 'UND_ERR_ABORTED' + } +} + +class InformationalError extends UndiciError { + constructor (message) { + super(message) + Error.captureStackTrace(this, InformationalError) + this.name = 'InformationalError' + this.message = message || 'Request information' + this.code = 'UND_ERR_INFO' + } +} + +class RequestContentLengthMismatchError extends UndiciError { + constructor (message) { + super(message) + Error.captureStackTrace(this, RequestContentLengthMismatchError) + this.name = 'RequestContentLengthMismatchError' + this.message = message || 'Request body length does not match content-length header' + this.code = 'UND_ERR_REQ_CONTENT_LENGTH_MISMATCH' + } +} + +class ResponseContentLengthMismatchError extends UndiciError { + constructor (message) { + super(message) + Error.captureStackTrace(this, ResponseContentLengthMismatchError) + this.name = 'ResponseContentLengthMismatchError' + this.message = message || 'Response body length does not match content-length header' + this.code = 'UND_ERR_RES_CONTENT_LENGTH_MISMATCH' + } +} + +class ClientDestroyedError extends UndiciError { + constructor (message) { + super(message) + Error.captureStackTrace(this, ClientDestroyedError) + this.name = 'ClientDestroyedError' + this.message = message || 'The client is destroyed' + this.code = 'UND_ERR_DESTROYED' + } +} + +class ClientClosedError extends UndiciError { + constructor (message) { + super(message) + Error.captureStackTrace(this, ClientClosedError) + this.name = 'ClientClosedError' + this.message = message || 'The client is closed' + this.code = 'UND_ERR_CLOSED' + } +} + +class SocketError extends UndiciError { + constructor (message, socket) { + super(message) + Error.captureStackTrace(this, SocketError) + this.name = 'SocketError' + this.message = message || 'Socket error' + this.code = 'UND_ERR_SOCKET' + this.socket = socket + } +} + +class NotSupportedError extends UndiciError { + constructor (message) { + super(message) + Error.captureStackTrace(this, NotSupportedError) + this.name = 'NotSupportedError' + this.message = message || 'Not supported error' + this.code = 'UND_ERR_NOT_SUPPORTED' + } +} + +class BalancedPoolMissingUpstreamError extends UndiciError { + constructor (message) { + super(message) + Error.captureStackTrace(this, NotSupportedError) + this.name = 'MissingUpstreamError' + this.message = message || 'No upstream has been added to the BalancedPool' + this.code = 'UND_ERR_BPL_MISSING_UPSTREAM' + } +} + +class HTTPParserError extends Error { + constructor (message, code, data) { + super(message) + Error.captureStackTrace(this, HTTPParserError) + this.name = 'HTTPParserError' + this.code = code ? `HPE_${code}` : undefined + this.data = data ? data.toString() : undefined + } +} + +class ResponseExceededMaxSizeError extends UndiciError { + constructor (message) { + super(message) + Error.captureStackTrace(this, ResponseExceededMaxSizeError) + this.name = 'ResponseExceededMaxSizeError' + this.message = message || 'Response content exceeded max size' + this.code = 'UND_ERR_RES_EXCEEDED_MAX_SIZE' + } +} + +class RequestRetryError extends UndiciError { + constructor (message, code, { headers, data }) { + super(message) + Error.captureStackTrace(this, RequestRetryError) + this.name = 'RequestRetryError' + this.message = message || 'Request retry error' + this.code = 'UND_ERR_REQ_RETRY' + this.statusCode = code + this.data = data + this.headers = headers + } +} + +module.exports = { + HTTPParserError, + UndiciError, + HeadersTimeoutError, + HeadersOverflowError, + BodyTimeoutError, + RequestContentLengthMismatchError, + ConnectTimeoutError, + ResponseStatusCodeError, + InvalidArgumentError, + InvalidReturnValueError, + RequestAbortedError, + ClientDestroyedError, + ClientClosedError, + InformationalError, + SocketError, + NotSupportedError, + ResponseContentLengthMismatchError, + BalancedPoolMissingUpstreamError, + ResponseExceededMaxSizeError, + RequestRetryError +} + + +/***/ }), + +/***/ 2690: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { + InvalidArgumentError, + NotSupportedError +} = __nccwpck_require__(721) +const assert = __nccwpck_require__(9491) +const { kHTTP2BuildRequest, kHTTP2CopyHeaders, kHTTP1BuildRequest } = __nccwpck_require__(9440) +const util = __nccwpck_require__(9522) + +// tokenRegExp and headerCharRegex have been lifted from +// https://github.com/nodejs/node/blob/main/lib/_http_common.js + +/** + * Verifies that the given val is a valid HTTP token + * per the rules defined in RFC 7230 + * See https://tools.ietf.org/html/rfc7230#section-3.2.6 + */ +const tokenRegExp = /^[\^_`a-zA-Z\-0-9!#$%&'*+.|~]+$/ + +/** + * Matches if val contains an invalid field-vchar + * field-value = *( field-content / obs-fold ) + * field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ] + * field-vchar = VCHAR / obs-text + */ +const headerCharRegex = /[^\t\x20-\x7e\x80-\xff]/ + +// Verifies that a given path is valid does not contain control chars \x00 to \x20 +const invalidPathRegex = /[^\u0021-\u00ff]/ + +const kHandler = Symbol('handler') + +const channels = {} + +let extractBody + +try { + const diagnosticsChannel = __nccwpck_require__(7643) + channels.create = diagnosticsChannel.channel('undici:request:create') + channels.bodySent = diagnosticsChannel.channel('undici:request:bodySent') + channels.headers = diagnosticsChannel.channel('undici:request:headers') + channels.trailers = diagnosticsChannel.channel('undici:request:trailers') + channels.error = diagnosticsChannel.channel('undici:request:error') +} catch { + channels.create = { hasSubscribers: false } + channels.bodySent = { hasSubscribers: false } + channels.headers = { hasSubscribers: false } + channels.trailers = { hasSubscribers: false } + channels.error = { hasSubscribers: false } +} + +class Request { + constructor (origin, { + path, + method, + body, + headers, + query, + idempotent, + blocking, + upgrade, + headersTimeout, + bodyTimeout, + reset, + throwOnError, + expectContinue + }, handler) { + if (typeof path !== 'string') { + throw new InvalidArgumentError('path must be a string') + } else if ( + path[0] !== '/' && + !(path.startsWith('http://') || path.startsWith('https://')) && + method !== 'CONNECT' + ) { + throw new InvalidArgumentError('path must be an absolute URL or start with a slash') + } else if (invalidPathRegex.exec(path) !== null) { + throw new InvalidArgumentError('invalid request path') + } + + if (typeof method !== 'string') { + throw new InvalidArgumentError('method must be a string') + } else if (tokenRegExp.exec(method) === null) { + throw new InvalidArgumentError('invalid request method') + } + + if (upgrade && typeof upgrade !== 'string') { + throw new InvalidArgumentError('upgrade must be a string') + } + + if (headersTimeout != null && (!Number.isFinite(headersTimeout) || headersTimeout < 0)) { + throw new InvalidArgumentError('invalid headersTimeout') + } + + if (bodyTimeout != null && (!Number.isFinite(bodyTimeout) || bodyTimeout < 0)) { + throw new InvalidArgumentError('invalid bodyTimeout') + } + + if (reset != null && typeof reset !== 'boolean') { + throw new InvalidArgumentError('invalid reset') + } + + if (expectContinue != null && typeof expectContinue !== 'boolean') { + throw new InvalidArgumentError('invalid expectContinue') + } + + this.headersTimeout = headersTimeout + + this.bodyTimeout = bodyTimeout + + this.throwOnError = throwOnError === true + + this.method = method + + this.abort = null + + if (body == null) { + this.body = null + } else if (util.isStream(body)) { + this.body = body + + const rState = this.body._readableState + if (!rState || !rState.autoDestroy) { + this.endHandler = function autoDestroy () { + util.destroy(this) + } + this.body.on('end', this.endHandler) + } + + this.errorHandler = err => { + if (this.abort) { + this.abort(err) + } else { + this.error = err + } + } + this.body.on('error', this.errorHandler) + } else if (util.isBuffer(body)) { + this.body = body.byteLength ? body : null + } else if (ArrayBuffer.isView(body)) { + this.body = body.buffer.byteLength ? Buffer.from(body.buffer, body.byteOffset, body.byteLength) : null + } else if (body instanceof ArrayBuffer) { + this.body = body.byteLength ? Buffer.from(body) : null + } else if (typeof body === 'string') { + this.body = body.length ? Buffer.from(body) : null + } else if (util.isFormDataLike(body) || util.isIterable(body) || util.isBlobLike(body)) { + this.body = body + } else { + throw new InvalidArgumentError('body must be a string, a Buffer, a Readable stream, an iterable, or an async iterable') + } + + this.completed = false + + this.aborted = false + + this.upgrade = upgrade || null + + this.path = query ? util.buildURL(path, query) : path + + this.origin = origin + + this.idempotent = idempotent == null + ? method === 'HEAD' || method === 'GET' + : idempotent + + this.blocking = blocking == null ? false : blocking + + this.reset = reset == null ? null : reset + + this.host = null + + this.contentLength = null + + this.contentType = null + + this.headers = '' + + // Only for H2 + this.expectContinue = expectContinue != null ? expectContinue : false + + if (Array.isArray(headers)) { + if (headers.length % 2 !== 0) { + throw new InvalidArgumentError('headers array must be even') + } + for (let i = 0; i < headers.length; i += 2) { + processHeader(this, headers[i], headers[i + 1]) + } + } else if (headers && typeof headers === 'object') { + const keys = Object.keys(headers) + for (let i = 0; i < keys.length; i++) { + const key = keys[i] + processHeader(this, key, headers[key]) + } + } else if (headers != null) { + throw new InvalidArgumentError('headers must be an object or an array') + } + + if (util.isFormDataLike(this.body)) { + if (util.nodeMajor < 16 || (util.nodeMajor === 16 && util.nodeMinor < 8)) { + throw new InvalidArgumentError('Form-Data bodies are only supported in node v16.8 and newer.') + } + + if (!extractBody) { + extractBody = (__nccwpck_require__(804).extractBody) + } + + const [bodyStream, contentType] = extractBody(body) + if (this.contentType == null) { + this.contentType = contentType + this.headers += `content-type: ${contentType}\r\n` + } + this.body = bodyStream.stream + this.contentLength = bodyStream.length + } else if (util.isBlobLike(body) && this.contentType == null && body.type) { + this.contentType = body.type + this.headers += `content-type: ${body.type}\r\n` + } + + util.validateHandler(handler, method, upgrade) + + this.servername = util.getServerName(this.host) + + this[kHandler] = handler + + if (channels.create.hasSubscribers) { + channels.create.publish({ request: this }) + } + } + + onBodySent (chunk) { + if (this[kHandler].onBodySent) { + try { + return this[kHandler].onBodySent(chunk) + } catch (err) { + this.abort(err) + } + } + } + + onRequestSent () { + if (channels.bodySent.hasSubscribers) { + channels.bodySent.publish({ request: this }) + } + + if (this[kHandler].onRequestSent) { + try { + return this[kHandler].onRequestSent() + } catch (err) { + this.abort(err) + } + } + } + + onConnect (abort) { + assert(!this.aborted) + assert(!this.completed) + + if (this.error) { + abort(this.error) + } else { + this.abort = abort + return this[kHandler].onConnect(abort) + } + } + + onHeaders (statusCode, headers, resume, statusText) { + assert(!this.aborted) + assert(!this.completed) + + if (channels.headers.hasSubscribers) { + channels.headers.publish({ request: this, response: { statusCode, headers, statusText } }) + } + + try { + return this[kHandler].onHeaders(statusCode, headers, resume, statusText) + } catch (err) { + this.abort(err) + } + } + + onData (chunk) { + assert(!this.aborted) + assert(!this.completed) + + try { + return this[kHandler].onData(chunk) + } catch (err) { + this.abort(err) + return false + } + } + + onUpgrade (statusCode, headers, socket) { + assert(!this.aborted) + assert(!this.completed) + + return this[kHandler].onUpgrade(statusCode, headers, socket) + } + + onComplete (trailers) { + this.onFinally() + + assert(!this.aborted) + + this.completed = true + if (channels.trailers.hasSubscribers) { + channels.trailers.publish({ request: this, trailers }) + } + + try { + return this[kHandler].onComplete(trailers) + } catch (err) { + // TODO (fix): This might be a bad idea? + this.onError(err) + } + } + + onError (error) { + this.onFinally() + + if (channels.error.hasSubscribers) { + channels.error.publish({ request: this, error }) + } + + if (this.aborted) { + return + } + this.aborted = true + + return this[kHandler].onError(error) + } + + onFinally () { + if (this.errorHandler) { + this.body.off('error', this.errorHandler) + this.errorHandler = null + } + + if (this.endHandler) { + this.body.off('end', this.endHandler) + this.endHandler = null + } + } + + // TODO: adjust to support H2 + addHeader (key, value) { + processHeader(this, key, value) + return this + } + + static [kHTTP1BuildRequest] (origin, opts, handler) { + // TODO: Migrate header parsing here, to make Requests + // HTTP agnostic + return new Request(origin, opts, handler) + } + + static [kHTTP2BuildRequest] (origin, opts, handler) { + const headers = opts.headers + opts = { ...opts, headers: null } + + const request = new Request(origin, opts, handler) + + request.headers = {} + + if (Array.isArray(headers)) { + if (headers.length % 2 !== 0) { + throw new InvalidArgumentError('headers array must be even') + } + for (let i = 0; i < headers.length; i += 2) { + processHeader(request, headers[i], headers[i + 1], true) + } + } else if (headers && typeof headers === 'object') { + const keys = Object.keys(headers) + for (let i = 0; i < keys.length; i++) { + const key = keys[i] + processHeader(request, key, headers[key], true) + } + } else if (headers != null) { + throw new InvalidArgumentError('headers must be an object or an array') + } + + return request + } + + static [kHTTP2CopyHeaders] (raw) { + const rawHeaders = raw.split('\r\n') + const headers = {} + + for (const header of rawHeaders) { + const [key, value] = header.split(': ') + + if (value == null || value.length === 0) continue + + if (headers[key]) headers[key] += `,${value}` + else headers[key] = value + } + + return headers + } +} + +function processHeaderValue (key, val, skipAppend) { + if (val && typeof val === 'object') { + throw new InvalidArgumentError(`invalid ${key} header`) + } + + val = val != null ? `${val}` : '' + + if (headerCharRegex.exec(val) !== null) { + throw new InvalidArgumentError(`invalid ${key} header`) + } + + return skipAppend ? val : `${key}: ${val}\r\n` +} + +function processHeader (request, key, val, skipAppend = false) { + if (val && (typeof val === 'object' && !Array.isArray(val))) { + throw new InvalidArgumentError(`invalid ${key} header`) + } else if (val === undefined) { + return + } + + if ( + request.host === null && + key.length === 4 && + key.toLowerCase() === 'host' + ) { + if (headerCharRegex.exec(val) !== null) { + throw new InvalidArgumentError(`invalid ${key} header`) + } + // Consumed by Client + request.host = val + } else if ( + request.contentLength === null && + key.length === 14 && + key.toLowerCase() === 'content-length' + ) { + request.contentLength = parseInt(val, 10) + if (!Number.isFinite(request.contentLength)) { + throw new InvalidArgumentError('invalid content-length header') + } + } else if ( + request.contentType === null && + key.length === 12 && + key.toLowerCase() === 'content-type' + ) { + request.contentType = val + if (skipAppend) request.headers[key] = processHeaderValue(key, val, skipAppend) + else request.headers += processHeaderValue(key, val) + } else if ( + key.length === 17 && + key.toLowerCase() === 'transfer-encoding' + ) { + throw new InvalidArgumentError('invalid transfer-encoding header') + } else if ( + key.length === 10 && + key.toLowerCase() === 'connection' + ) { + const value = typeof val === 'string' ? val.toLowerCase() : null + if (value !== 'close' && value !== 'keep-alive') { + throw new InvalidArgumentError('invalid connection header') + } else if (value === 'close') { + request.reset = true + } + } else if ( + key.length === 10 && + key.toLowerCase() === 'keep-alive' + ) { + throw new InvalidArgumentError('invalid keep-alive header') + } else if ( + key.length === 7 && + key.toLowerCase() === 'upgrade' + ) { + throw new InvalidArgumentError('invalid upgrade header') + } else if ( + key.length === 6 && + key.toLowerCase() === 'expect' + ) { + throw new NotSupportedError('expect header not supported') + } else if (tokenRegExp.exec(key) === null) { + throw new InvalidArgumentError('invalid header key') + } else { + if (Array.isArray(val)) { + for (let i = 0; i < val.length; i++) { + if (skipAppend) { + if (request.headers[key]) request.headers[key] += `,${processHeaderValue(key, val[i], skipAppend)}` + else request.headers[key] = processHeaderValue(key, val[i], skipAppend) + } else { + request.headers += processHeaderValue(key, val[i]) + } + } + } else { + if (skipAppend) request.headers[key] = processHeaderValue(key, val, skipAppend) + else request.headers += processHeaderValue(key, val) + } + } +} + +module.exports = Request + + +/***/ }), + +/***/ 9440: +/***/ ((module) => { + +module.exports = { + kClose: Symbol('close'), + kDestroy: Symbol('destroy'), + kDispatch: Symbol('dispatch'), + kUrl: Symbol('url'), + kWriting: Symbol('writing'), + kResuming: Symbol('resuming'), + kQueue: Symbol('queue'), + kConnect: Symbol('connect'), + kConnecting: Symbol('connecting'), + kHeadersList: Symbol('headers list'), + kKeepAliveDefaultTimeout: Symbol('default keep alive timeout'), + kKeepAliveMaxTimeout: Symbol('max keep alive timeout'), + kKeepAliveTimeoutThreshold: Symbol('keep alive timeout threshold'), + kKeepAliveTimeoutValue: Symbol('keep alive timeout'), + kKeepAlive: Symbol('keep alive'), + kHeadersTimeout: Symbol('headers timeout'), + kBodyTimeout: Symbol('body timeout'), + kServerName: Symbol('server name'), + kLocalAddress: Symbol('local address'), + kHost: Symbol('host'), + kNoRef: Symbol('no ref'), + kBodyUsed: Symbol('used'), + kRunning: Symbol('running'), + kBlocking: Symbol('blocking'), + kPending: Symbol('pending'), + kSize: Symbol('size'), + kBusy: Symbol('busy'), + kQueued: Symbol('queued'), + kFree: Symbol('free'), + kConnected: Symbol('connected'), + kClosed: Symbol('closed'), + kNeedDrain: Symbol('need drain'), + kReset: Symbol('reset'), + kDestroyed: Symbol.for('nodejs.stream.destroyed'), + kMaxHeadersSize: Symbol('max headers size'), + kRunningIdx: Symbol('running index'), + kPendingIdx: Symbol('pending index'), + kError: Symbol('error'), + kClients: Symbol('clients'), + kClient: Symbol('client'), + kParser: Symbol('parser'), + kOnDestroyed: Symbol('destroy callbacks'), + kPipelining: Symbol('pipelining'), + kSocket: Symbol('socket'), + kHostHeader: Symbol('host header'), + kConnector: Symbol('connector'), + kStrictContentLength: Symbol('strict content length'), + kMaxRedirections: Symbol('maxRedirections'), + kMaxRequests: Symbol('maxRequestsPerClient'), + kProxy: Symbol('proxy agent options'), + kCounter: Symbol('socket request counter'), + kInterceptors: Symbol('dispatch interceptors'), + kMaxResponseSize: Symbol('max response size'), + kHTTP2Session: Symbol('http2Session'), + kHTTP2SessionState: Symbol('http2Session state'), + kHTTP2BuildRequest: Symbol('http2 build request'), + kHTTP1BuildRequest: Symbol('http1 build request'), + kHTTP2CopyHeaders: Symbol('http2 copy headers'), + kHTTPConnVersion: Symbol('http connection version'), + kRetryHandlerDefaultRetry: Symbol('retry agent default retry') +} + + +/***/ }), + +/***/ 9522: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const assert = __nccwpck_require__(9491) +const { kDestroyed, kBodyUsed } = __nccwpck_require__(9440) +const { IncomingMessage } = __nccwpck_require__(3685) +const stream = __nccwpck_require__(2781) +const net = __nccwpck_require__(1808) +const { InvalidArgumentError } = __nccwpck_require__(721) +const { Blob } = __nccwpck_require__(4300) +const nodeUtil = __nccwpck_require__(3837) +const { stringify } = __nccwpck_require__(3477) + +const [nodeMajor, nodeMinor] = process.versions.node.split('.').map(v => Number(v)) + +function nop () {} + +function isStream (obj) { + return obj && typeof obj === 'object' && typeof obj.pipe === 'function' && typeof obj.on === 'function' +} + +// based on https://github.com/node-fetch/fetch-blob/blob/8ab587d34080de94140b54f07168451e7d0b655e/index.js#L229-L241 (MIT License) +function isBlobLike (object) { + return (Blob && object instanceof Blob) || ( + object && + typeof object === 'object' && + (typeof object.stream === 'function' || + typeof object.arrayBuffer === 'function') && + /^(Blob|File)$/.test(object[Symbol.toStringTag]) + ) +} + +function buildURL (url, queryParams) { + if (url.includes('?') || url.includes('#')) { + throw new Error('Query params cannot be passed when url already contains "?" or "#".') + } + + const stringified = stringify(queryParams) + + if (stringified) { + url += '?' + stringified + } + + return url +} + +function parseURL (url) { + if (typeof url === 'string') { + url = new URL(url) + + if (!/^https?:/.test(url.origin || url.protocol)) { + throw new InvalidArgumentError('Invalid URL protocol: the URL must start with `http:` or `https:`.') + } + + return url + } + + if (!url || typeof url !== 'object') { + throw new InvalidArgumentError('Invalid URL: The URL argument must be a non-null object.') + } + + if (!/^https?:/.test(url.origin || url.protocol)) { + throw new InvalidArgumentError('Invalid URL protocol: the URL must start with `http:` or `https:`.') + } + + if (!(url instanceof URL)) { + if (url.port != null && url.port !== '' && !Number.isFinite(parseInt(url.port))) { + throw new InvalidArgumentError('Invalid URL: port must be a valid integer or a string representation of an integer.') + } + + if (url.path != null && typeof url.path !== 'string') { + throw new InvalidArgumentError('Invalid URL path: the path must be a string or null/undefined.') + } + + if (url.pathname != null && typeof url.pathname !== 'string') { + throw new InvalidArgumentError('Invalid URL pathname: the pathname must be a string or null/undefined.') + } + + if (url.hostname != null && typeof url.hostname !== 'string') { + throw new InvalidArgumentError('Invalid URL hostname: the hostname must be a string or null/undefined.') + } + + if (url.origin != null && typeof url.origin !== 'string') { + throw new InvalidArgumentError('Invalid URL origin: the origin must be a string or null/undefined.') + } + + const port = url.port != null + ? url.port + : (url.protocol === 'https:' ? 443 : 80) + let origin = url.origin != null + ? url.origin + : `${url.protocol}//${url.hostname}:${port}` + let path = url.path != null + ? url.path + : `${url.pathname || ''}${url.search || ''}` + + if (origin.endsWith('/')) { + origin = origin.substring(0, origin.length - 1) + } + + if (path && !path.startsWith('/')) { + path = `/${path}` + } + // new URL(path, origin) is unsafe when `path` contains an absolute URL + // From https://developer.mozilla.org/en-US/docs/Web/API/URL/URL: + // If first parameter is a relative URL, second param is required, and will be used as the base URL. + // If first parameter is an absolute URL, a given second param will be ignored. + url = new URL(origin + path) + } + + return url +} + +function parseOrigin (url) { + url = parseURL(url) + + if (url.pathname !== '/' || url.search || url.hash) { + throw new InvalidArgumentError('invalid url') + } + + return url +} + +function getHostname (host) { + if (host[0] === '[') { + const idx = host.indexOf(']') + + assert(idx !== -1) + return host.substring(1, idx) + } + + const idx = host.indexOf(':') + if (idx === -1) return host + + return host.substring(0, idx) +} + +// IP addresses are not valid server names per RFC6066 +// > Currently, the only server names supported are DNS hostnames +function getServerName (host) { + if (!host) { + return null + } + + assert.strictEqual(typeof host, 'string') + + const servername = getHostname(host) + if (net.isIP(servername)) { + return '' + } + + return servername +} + +function deepClone (obj) { + return JSON.parse(JSON.stringify(obj)) +} + +function isAsyncIterable (obj) { + return !!(obj != null && typeof obj[Symbol.asyncIterator] === 'function') +} + +function isIterable (obj) { + return !!(obj != null && (typeof obj[Symbol.iterator] === 'function' || typeof obj[Symbol.asyncIterator] === 'function')) +} + +function bodyLength (body) { + if (body == null) { + return 0 + } else if (isStream(body)) { + const state = body._readableState + return state && state.objectMode === false && state.ended === true && Number.isFinite(state.length) + ? state.length + : null + } else if (isBlobLike(body)) { + return body.size != null ? body.size : null + } else if (isBuffer(body)) { + return body.byteLength + } + + return null +} + +function isDestroyed (stream) { + return !stream || !!(stream.destroyed || stream[kDestroyed]) +} + +function isReadableAborted (stream) { + const state = stream && stream._readableState + return isDestroyed(stream) && state && !state.endEmitted +} + +function destroy (stream, err) { + if (stream == null || !isStream(stream) || isDestroyed(stream)) { + return + } + + if (typeof stream.destroy === 'function') { + if (Object.getPrototypeOf(stream).constructor === IncomingMessage) { + // See: https://github.com/nodejs/node/pull/38505/files + stream.socket = null + } + + stream.destroy(err) + } else if (err) { + process.nextTick((stream, err) => { + stream.emit('error', err) + }, stream, err) + } + + if (stream.destroyed !== true) { + stream[kDestroyed] = true + } +} + +const KEEPALIVE_TIMEOUT_EXPR = /timeout=(\d+)/ +function parseKeepAliveTimeout (val) { + const m = val.toString().match(KEEPALIVE_TIMEOUT_EXPR) + return m ? parseInt(m[1], 10) * 1000 : null +} + +function parseHeaders (headers, obj = {}) { + // For H2 support + if (!Array.isArray(headers)) return headers + + for (let i = 0; i < headers.length; i += 2) { + const key = headers[i].toString().toLowerCase() + let val = obj[key] + + if (!val) { + if (Array.isArray(headers[i + 1])) { + obj[key] = headers[i + 1].map(x => x.toString('utf8')) + } else { + obj[key] = headers[i + 1].toString('utf8') + } + } else { + if (!Array.isArray(val)) { + val = [val] + obj[key] = val + } + val.push(headers[i + 1].toString('utf8')) + } + } + + // See https://github.com/nodejs/node/pull/46528 + if ('content-length' in obj && 'content-disposition' in obj) { + obj['content-disposition'] = Buffer.from(obj['content-disposition']).toString('latin1') + } + + return obj +} + +function parseRawHeaders (headers) { + const ret = [] + let hasContentLength = false + let contentDispositionIdx = -1 + + for (let n = 0; n < headers.length; n += 2) { + const key = headers[n + 0].toString() + const val = headers[n + 1].toString('utf8') + + if (key.length === 14 && (key === 'content-length' || key.toLowerCase() === 'content-length')) { + ret.push(key, val) + hasContentLength = true + } else if (key.length === 19 && (key === 'content-disposition' || key.toLowerCase() === 'content-disposition')) { + contentDispositionIdx = ret.push(key, val) - 1 + } else { + ret.push(key, val) + } + } + + // See https://github.com/nodejs/node/pull/46528 + if (hasContentLength && contentDispositionIdx !== -1) { + ret[contentDispositionIdx] = Buffer.from(ret[contentDispositionIdx]).toString('latin1') + } + + return ret +} + +function isBuffer (buffer) { + // See, https://github.com/mcollina/undici/pull/319 + return buffer instanceof Uint8Array || Buffer.isBuffer(buffer) +} + +function validateHandler (handler, method, upgrade) { + if (!handler || typeof handler !== 'object') { + throw new InvalidArgumentError('handler must be an object') + } + + if (typeof handler.onConnect !== 'function') { + throw new InvalidArgumentError('invalid onConnect method') + } + + if (typeof handler.onError !== 'function') { + throw new InvalidArgumentError('invalid onError method') + } + + if (typeof handler.onBodySent !== 'function' && handler.onBodySent !== undefined) { + throw new InvalidArgumentError('invalid onBodySent method') + } + + if (upgrade || method === 'CONNECT') { + if (typeof handler.onUpgrade !== 'function') { + throw new InvalidArgumentError('invalid onUpgrade method') + } + } else { + if (typeof handler.onHeaders !== 'function') { + throw new InvalidArgumentError('invalid onHeaders method') + } + + if (typeof handler.onData !== 'function') { + throw new InvalidArgumentError('invalid onData method') + } + + if (typeof handler.onComplete !== 'function') { + throw new InvalidArgumentError('invalid onComplete method') + } + } +} + +// A body is disturbed if it has been read from and it cannot +// be re-used without losing state or data. +function isDisturbed (body) { + return !!(body && ( + stream.isDisturbed + ? stream.isDisturbed(body) || body[kBodyUsed] // TODO (fix): Why is body[kBodyUsed] needed? + : body[kBodyUsed] || + body.readableDidRead || + (body._readableState && body._readableState.dataEmitted) || + isReadableAborted(body) + )) +} + +function isErrored (body) { + return !!(body && ( + stream.isErrored + ? stream.isErrored(body) + : /state: 'errored'/.test(nodeUtil.inspect(body) + ))) +} + +function isReadable (body) { + return !!(body && ( + stream.isReadable + ? stream.isReadable(body) + : /state: 'readable'/.test(nodeUtil.inspect(body) + ))) +} + +function getSocketInfo (socket) { + return { + localAddress: socket.localAddress, + localPort: socket.localPort, + remoteAddress: socket.remoteAddress, + remotePort: socket.remotePort, + remoteFamily: socket.remoteFamily, + timeout: socket.timeout, + bytesWritten: socket.bytesWritten, + bytesRead: socket.bytesRead + } +} + +async function * convertIterableToBuffer (iterable) { + for await (const chunk of iterable) { + yield Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk) + } +} + +let ReadableStream +function ReadableStreamFrom (iterable) { + if (!ReadableStream) { + ReadableStream = (__nccwpck_require__(5356).ReadableStream) + } + + if (ReadableStream.from) { + return ReadableStream.from(convertIterableToBuffer(iterable)) + } + + let iterator + return new ReadableStream( + { + async start () { + iterator = iterable[Symbol.asyncIterator]() + }, + async pull (controller) { + const { done, value } = await iterator.next() + if (done) { + queueMicrotask(() => { + controller.close() + }) + } else { + const buf = Buffer.isBuffer(value) ? value : Buffer.from(value) + controller.enqueue(new Uint8Array(buf)) + } + return controller.desiredSize > 0 + }, + async cancel (reason) { + await iterator.return() + } + }, + 0 + ) +} + +// The chunk should be a FormData instance and contains +// all the required methods. +function isFormDataLike (object) { + return ( + object && + typeof object === 'object' && + typeof object.append === 'function' && + typeof object.delete === 'function' && + typeof object.get === 'function' && + typeof object.getAll === 'function' && + typeof object.has === 'function' && + typeof object.set === 'function' && + object[Symbol.toStringTag] === 'FormData' + ) +} + +function throwIfAborted (signal) { + if (!signal) { return } + if (typeof signal.throwIfAborted === 'function') { + signal.throwIfAborted() + } else { + if (signal.aborted) { + // DOMException not available < v17.0.0 + const err = new Error('The operation was aborted') + err.name = 'AbortError' + throw err + } + } +} + +function addAbortListener (signal, listener) { + if ('addEventListener' in signal) { + signal.addEventListener('abort', listener, { once: true }) + return () => signal.removeEventListener('abort', listener) + } + signal.addListener('abort', listener) + return () => signal.removeListener('abort', listener) +} + +const hasToWellFormed = !!String.prototype.toWellFormed + +/** + * @param {string} val + */ +function toUSVString (val) { + if (hasToWellFormed) { + return `${val}`.toWellFormed() + } else if (nodeUtil.toUSVString) { + return nodeUtil.toUSVString(val) + } + + return `${val}` +} + +// Parsed accordingly to RFC 9110 +// https://www.rfc-editor.org/rfc/rfc9110#field.content-range +function parseRangeHeader (range) { + if (range == null || range === '') return { start: 0, end: null, size: null } + + const m = range ? range.match(/^bytes (\d+)-(\d+)\/(\d+)?$/) : null + return m + ? { + start: parseInt(m[1]), + end: m[2] ? parseInt(m[2]) : null, + size: m[3] ? parseInt(m[3]) : null + } + : null +} + +const kEnumerableProperty = Object.create(null) +kEnumerableProperty.enumerable = true + +module.exports = { + kEnumerableProperty, + nop, + isDisturbed, + isErrored, + isReadable, + toUSVString, + isReadableAborted, + isBlobLike, + parseOrigin, + parseURL, + getServerName, + isStream, + isIterable, + isAsyncIterable, + isDestroyed, + parseRawHeaders, + parseHeaders, + parseKeepAliveTimeout, + destroy, + bodyLength, + deepClone, + ReadableStreamFrom, + isBuffer, + validateHandler, + getSocketInfo, + isFormDataLike, + buildURL, + throwIfAborted, + addAbortListener, + parseRangeHeader, + nodeMajor, + nodeMinor, + nodeHasAutoSelectFamily: nodeMajor > 18 || (nodeMajor === 18 && nodeMinor >= 13), + safeHTTPMethods: ['GET', 'HEAD', 'OPTIONS', 'TRACE'] +} + + +/***/ }), + +/***/ 8462: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const Dispatcher = __nccwpck_require__(6504) +const { + ClientDestroyedError, + ClientClosedError, + InvalidArgumentError +} = __nccwpck_require__(721) +const { kDestroy, kClose, kDispatch, kInterceptors } = __nccwpck_require__(9440) + +const kDestroyed = Symbol('destroyed') +const kClosed = Symbol('closed') +const kOnDestroyed = Symbol('onDestroyed') +const kOnClosed = Symbol('onClosed') +const kInterceptedDispatch = Symbol('Intercepted Dispatch') + +class DispatcherBase extends Dispatcher { + constructor () { + super() + + this[kDestroyed] = false + this[kOnDestroyed] = null + this[kClosed] = false + this[kOnClosed] = [] + } + + get destroyed () { + return this[kDestroyed] + } + + get closed () { + return this[kClosed] + } + + get interceptors () { + return this[kInterceptors] + } + + set interceptors (newInterceptors) { + if (newInterceptors) { + for (let i = newInterceptors.length - 1; i >= 0; i--) { + const interceptor = this[kInterceptors][i] + if (typeof interceptor !== 'function') { + throw new InvalidArgumentError('interceptor must be an function') + } + } + } + + this[kInterceptors] = newInterceptors + } + + close (callback) { + if (callback === undefined) { + return new Promise((resolve, reject) => { + this.close((err, data) => { + return err ? reject(err) : resolve(data) + }) + }) + } + + if (typeof callback !== 'function') { + throw new InvalidArgumentError('invalid callback') + } + + if (this[kDestroyed]) { + queueMicrotask(() => callback(new ClientDestroyedError(), null)) + return + } + + if (this[kClosed]) { + if (this[kOnClosed]) { + this[kOnClosed].push(callback) + } else { + queueMicrotask(() => callback(null, null)) + } + return + } + + this[kClosed] = true + this[kOnClosed].push(callback) + + const onClosed = () => { + const callbacks = this[kOnClosed] + this[kOnClosed] = null + for (let i = 0; i < callbacks.length; i++) { + callbacks[i](null, null) + } + } + + // Should not error. + this[kClose]() + .then(() => this.destroy()) + .then(() => { + queueMicrotask(onClosed) + }) + } + + destroy (err, callback) { + if (typeof err === 'function') { + callback = err + err = null + } + + if (callback === undefined) { + return new Promise((resolve, reject) => { + this.destroy(err, (err, data) => { + return err ? /* istanbul ignore next: should never error */ reject(err) : resolve(data) + }) + }) + } + + if (typeof callback !== 'function') { + throw new InvalidArgumentError('invalid callback') + } + + if (this[kDestroyed]) { + if (this[kOnDestroyed]) { + this[kOnDestroyed].push(callback) + } else { + queueMicrotask(() => callback(null, null)) + } + return + } + + if (!err) { + err = new ClientDestroyedError() + } + + this[kDestroyed] = true + this[kOnDestroyed] = this[kOnDestroyed] || [] + this[kOnDestroyed].push(callback) + + const onDestroyed = () => { + const callbacks = this[kOnDestroyed] + this[kOnDestroyed] = null + for (let i = 0; i < callbacks.length; i++) { + callbacks[i](null, null) + } + } + + // Should not error. + this[kDestroy](err).then(() => { + queueMicrotask(onDestroyed) + }) + } + + [kInterceptedDispatch] (opts, handler) { + if (!this[kInterceptors] || this[kInterceptors].length === 0) { + this[kInterceptedDispatch] = this[kDispatch] + return this[kDispatch](opts, handler) + } + + let dispatch = this[kDispatch].bind(this) + for (let i = this[kInterceptors].length - 1; i >= 0; i--) { + dispatch = this[kInterceptors][i](dispatch) + } + this[kInterceptedDispatch] = dispatch + return dispatch(opts, handler) + } + + dispatch (opts, handler) { + if (!handler || typeof handler !== 'object') { + throw new InvalidArgumentError('handler must be an object') + } + + try { + if (!opts || typeof opts !== 'object') { + throw new InvalidArgumentError('opts must be an object.') + } + + if (this[kDestroyed] || this[kOnDestroyed]) { + throw new ClientDestroyedError() + } + + if (this[kClosed]) { + throw new ClientClosedError() + } + + return this[kInterceptedDispatch](opts, handler) + } catch (err) { + if (typeof handler.onError !== 'function') { + throw new InvalidArgumentError('invalid onError method') + } + + handler.onError(err) + + return false + } + } +} + +module.exports = DispatcherBase + + +/***/ }), + +/***/ 6504: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const EventEmitter = __nccwpck_require__(2361) + +class Dispatcher extends EventEmitter { + dispatch () { + throw new Error('not implemented') + } + + close () { + throw new Error('not implemented') + } + + destroy () { + throw new Error('not implemented') + } +} + +module.exports = Dispatcher + + +/***/ }), + +/***/ 804: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const Busboy = __nccwpck_require__(8162) +const util = __nccwpck_require__(9522) +const { + ReadableStreamFrom, + isBlobLike, + isReadableStreamLike, + readableStreamClose, + createDeferredPromise, + fullyReadBody +} = __nccwpck_require__(784) +const { FormData } = __nccwpck_require__(968) +const { kState } = __nccwpck_require__(8085) +const { webidl } = __nccwpck_require__(1537) +const { DOMException, structuredClone } = __nccwpck_require__(7059) +const { Blob, File: NativeFile } = __nccwpck_require__(4300) +const { kBodyUsed } = __nccwpck_require__(9440) +const assert = __nccwpck_require__(9491) +const { isErrored } = __nccwpck_require__(9522) +const { isUint8Array, isArrayBuffer } = __nccwpck_require__(9830) +const { File: UndiciFile } = __nccwpck_require__(5479) +const { parseMIMEType, serializeAMimeType } = __nccwpck_require__(2791) + +let ReadableStream = globalThis.ReadableStream + +/** @type {globalThis['File']} */ +const File = NativeFile ?? UndiciFile +const textEncoder = new TextEncoder() +const textDecoder = new TextDecoder() + +// https://fetch.spec.whatwg.org/#concept-bodyinit-extract +function extractBody (object, keepalive = false) { + if (!ReadableStream) { + ReadableStream = (__nccwpck_require__(5356).ReadableStream) + } + + // 1. Let stream be null. + let stream = null + + // 2. If object is a ReadableStream object, then set stream to object. + if (object instanceof ReadableStream) { + stream = object + } else if (isBlobLike(object)) { + // 3. Otherwise, if object is a Blob object, set stream to the + // result of running object’s get stream. + stream = object.stream() + } else { + // 4. Otherwise, set stream to a new ReadableStream object, and set + // up stream. + stream = new ReadableStream({ + async pull (controller) { + controller.enqueue( + typeof source === 'string' ? textEncoder.encode(source) : source + ) + queueMicrotask(() => readableStreamClose(controller)) + }, + start () {}, + type: undefined + }) + } + + // 5. Assert: stream is a ReadableStream object. + assert(isReadableStreamLike(stream)) + + // 6. Let action be null. + let action = null + + // 7. Let source be null. + let source = null + + // 8. Let length be null. + let length = null + + // 9. Let type be null. + let type = null + + // 10. Switch on object: + if (typeof object === 'string') { + // Set source to the UTF-8 encoding of object. + // Note: setting source to a Uint8Array here breaks some mocking assumptions. + source = object + + // Set type to `text/plain;charset=UTF-8`. + type = 'text/plain;charset=UTF-8' + } else if (object instanceof URLSearchParams) { + // URLSearchParams + + // spec says to run application/x-www-form-urlencoded on body.list + // this is implemented in Node.js as apart of an URLSearchParams instance toString method + // See: https://github.com/nodejs/node/blob/e46c680bf2b211bbd52cf959ca17ee98c7f657f5/lib/internal/url.js#L490 + // and https://github.com/nodejs/node/blob/e46c680bf2b211bbd52cf959ca17ee98c7f657f5/lib/internal/url.js#L1100 + + // Set source to the result of running the application/x-www-form-urlencoded serializer with object’s list. + source = object.toString() + + // Set type to `application/x-www-form-urlencoded;charset=UTF-8`. + type = 'application/x-www-form-urlencoded;charset=UTF-8' + } else if (isArrayBuffer(object)) { + // BufferSource/ArrayBuffer + + // Set source to a copy of the bytes held by object. + source = new Uint8Array(object.slice()) + } else if (ArrayBuffer.isView(object)) { + // BufferSource/ArrayBufferView + + // Set source to a copy of the bytes held by object. + source = new Uint8Array(object.buffer.slice(object.byteOffset, object.byteOffset + object.byteLength)) + } else if (util.isFormDataLike(object)) { + const boundary = `----formdata-undici-0${`${Math.floor(Math.random() * 1e11)}`.padStart(11, '0')}` + const prefix = `--${boundary}\r\nContent-Disposition: form-data` + + /*! formdata-polyfill. MIT License. Jimmy Wärting */ + const escape = (str) => + str.replace(/\n/g, '%0A').replace(/\r/g, '%0D').replace(/"/g, '%22') + const normalizeLinefeeds = (value) => value.replace(/\r?\n|\r/g, '\r\n') + + // Set action to this step: run the multipart/form-data + // encoding algorithm, with object’s entry list and UTF-8. + // - This ensures that the body is immutable and can't be changed afterwords + // - That the content-length is calculated in advance. + // - And that all parts are pre-encoded and ready to be sent. + + const blobParts = [] + const rn = new Uint8Array([13, 10]) // '\r\n' + length = 0 + let hasUnknownSizeValue = false + + for (const [name, value] of object) { + if (typeof value === 'string') { + const chunk = textEncoder.encode(prefix + + `; name="${escape(normalizeLinefeeds(name))}"` + + `\r\n\r\n${normalizeLinefeeds(value)}\r\n`) + blobParts.push(chunk) + length += chunk.byteLength + } else { + const chunk = textEncoder.encode(`${prefix}; name="${escape(normalizeLinefeeds(name))}"` + + (value.name ? `; filename="${escape(value.name)}"` : '') + '\r\n' + + `Content-Type: ${ + value.type || 'application/octet-stream' + }\r\n\r\n`) + blobParts.push(chunk, value, rn) + if (typeof value.size === 'number') { + length += chunk.byteLength + value.size + rn.byteLength + } else { + hasUnknownSizeValue = true + } + } + } + + const chunk = textEncoder.encode(`--${boundary}--`) + blobParts.push(chunk) + length += chunk.byteLength + if (hasUnknownSizeValue) { + length = null + } + + // Set source to object. + source = object + + action = async function * () { + for (const part of blobParts) { + if (part.stream) { + yield * part.stream() + } else { + yield part + } + } + } + + // Set type to `multipart/form-data; boundary=`, + // followed by the multipart/form-data boundary string generated + // by the multipart/form-data encoding algorithm. + type = 'multipart/form-data; boundary=' + boundary + } else if (isBlobLike(object)) { + // Blob + + // Set source to object. + source = object + + // Set length to object’s size. + length = object.size + + // If object’s type attribute is not the empty byte sequence, set + // type to its value. + if (object.type) { + type = object.type + } + } else if (typeof object[Symbol.asyncIterator] === 'function') { + // If keepalive is true, then throw a TypeError. + if (keepalive) { + throw new TypeError('keepalive') + } + + // If object is disturbed or locked, then throw a TypeError. + if (util.isDisturbed(object) || object.locked) { + throw new TypeError( + 'Response body object should not be disturbed or locked' + ) + } + + stream = + object instanceof ReadableStream ? object : ReadableStreamFrom(object) + } + + // 11. If source is a byte sequence, then set action to a + // step that returns source and length to source’s length. + if (typeof source === 'string' || util.isBuffer(source)) { + length = Buffer.byteLength(source) + } + + // 12. If action is non-null, then run these steps in in parallel: + if (action != null) { + // Run action. + let iterator + stream = new ReadableStream({ + async start () { + iterator = action(object)[Symbol.asyncIterator]() + }, + async pull (controller) { + const { value, done } = await iterator.next() + if (done) { + // When running action is done, close stream. + queueMicrotask(() => { + controller.close() + }) + } else { + // Whenever one or more bytes are available and stream is not errored, + // enqueue a Uint8Array wrapping an ArrayBuffer containing the available + // bytes into stream. + if (!isErrored(stream)) { + controller.enqueue(new Uint8Array(value)) + } + } + return controller.desiredSize > 0 + }, + async cancel (reason) { + await iterator.return() + }, + type: undefined + }) + } + + // 13. Let body be a body whose stream is stream, source is source, + // and length is length. + const body = { stream, source, length } + + // 14. Return (body, type). + return [body, type] +} + +// https://fetch.spec.whatwg.org/#bodyinit-safely-extract +function safelyExtractBody (object, keepalive = false) { + if (!ReadableStream) { + // istanbul ignore next + ReadableStream = (__nccwpck_require__(5356).ReadableStream) + } + + // To safely extract a body and a `Content-Type` value from + // a byte sequence or BodyInit object object, run these steps: + + // 1. If object is a ReadableStream object, then: + if (object instanceof ReadableStream) { + // Assert: object is neither disturbed nor locked. + // istanbul ignore next + assert(!util.isDisturbed(object), 'The body has already been consumed.') + // istanbul ignore next + assert(!object.locked, 'The stream is locked.') + } + + // 2. Return the results of extracting object. + return extractBody(object, keepalive) +} + +function cloneBody (body) { + // To clone a body body, run these steps: + + // https://fetch.spec.whatwg.org/#concept-body-clone + + // 1. Let « out1, out2 » be the result of teeing body’s stream. + const [out1, out2] = body.stream.tee() + const out2Clone = structuredClone(out2, { transfer: [out2] }) + // This, for whatever reasons, unrefs out2Clone which allows + // the process to exit by itself. + const [, finalClone] = out2Clone.tee() + + // 2. Set body’s stream to out1. + body.stream = out1 + + // 3. Return a body whose stream is out2 and other members are copied from body. + return { + stream: finalClone, + length: body.length, + source: body.source + } +} + +async function * consumeBody (body) { + if (body) { + if (isUint8Array(body)) { + yield body + } else { + const stream = body.stream + + if (util.isDisturbed(stream)) { + throw new TypeError('The body has already been consumed.') + } + + if (stream.locked) { + throw new TypeError('The stream is locked.') + } + + // Compat. + stream[kBodyUsed] = true + + yield * stream + } + } +} + +function throwIfAborted (state) { + if (state.aborted) { + throw new DOMException('The operation was aborted.', 'AbortError') + } +} + +function bodyMixinMethods (instance) { + const methods = { + blob () { + // The blob() method steps are to return the result of + // running consume body with this and the following step + // given a byte sequence bytes: return a Blob whose + // contents are bytes and whose type attribute is this’s + // MIME type. + return specConsumeBody(this, (bytes) => { + let mimeType = bodyMimeType(this) + + if (mimeType === 'failure') { + mimeType = '' + } else if (mimeType) { + mimeType = serializeAMimeType(mimeType) + } + + // Return a Blob whose contents are bytes and type attribute + // is mimeType. + return new Blob([bytes], { type: mimeType }) + }, instance) + }, + + arrayBuffer () { + // The arrayBuffer() method steps are to return the result + // of running consume body with this and the following step + // given a byte sequence bytes: return a new ArrayBuffer + // whose contents are bytes. + return specConsumeBody(this, (bytes) => { + return new Uint8Array(bytes).buffer + }, instance) + }, + + text () { + // The text() method steps are to return the result of running + // consume body with this and UTF-8 decode. + return specConsumeBody(this, utf8DecodeBytes, instance) + }, + + json () { + // The json() method steps are to return the result of running + // consume body with this and parse JSON from bytes. + return specConsumeBody(this, parseJSONFromBytes, instance) + }, + + async formData () { + webidl.brandCheck(this, instance) + + throwIfAborted(this[kState]) + + const contentType = this.headers.get('Content-Type') + + // If mimeType’s essence is "multipart/form-data", then: + if (/multipart\/form-data/.test(contentType)) { + const headers = {} + for (const [key, value] of this.headers) headers[key.toLowerCase()] = value + + const responseFormData = new FormData() + + let busboy + + try { + busboy = new Busboy({ + headers, + preservePath: true + }) + } catch (err) { + throw new DOMException(`${err}`, 'AbortError') + } + + busboy.on('field', (name, value) => { + responseFormData.append(name, value) + }) + busboy.on('file', (name, value, filename, encoding, mimeType) => { + const chunks = [] + + if (encoding === 'base64' || encoding.toLowerCase() === 'base64') { + let base64chunk = '' + + value.on('data', (chunk) => { + base64chunk += chunk.toString().replace(/[\r\n]/gm, '') + + const end = base64chunk.length - base64chunk.length % 4 + chunks.push(Buffer.from(base64chunk.slice(0, end), 'base64')) + + base64chunk = base64chunk.slice(end) + }) + value.on('end', () => { + chunks.push(Buffer.from(base64chunk, 'base64')) + responseFormData.append(name, new File(chunks, filename, { type: mimeType })) + }) + } else { + value.on('data', (chunk) => { + chunks.push(chunk) + }) + value.on('end', () => { + responseFormData.append(name, new File(chunks, filename, { type: mimeType })) + }) + } + }) + + const busboyResolve = new Promise((resolve, reject) => { + busboy.on('finish', resolve) + busboy.on('error', (err) => reject(new TypeError(err))) + }) + + if (this.body !== null) for await (const chunk of consumeBody(this[kState].body)) busboy.write(chunk) + busboy.end() + await busboyResolve + + return responseFormData + } else if (/application\/x-www-form-urlencoded/.test(contentType)) { + // Otherwise, if mimeType’s essence is "application/x-www-form-urlencoded", then: + + // 1. Let entries be the result of parsing bytes. + let entries + try { + let text = '' + // application/x-www-form-urlencoded parser will keep the BOM. + // https://url.spec.whatwg.org/#concept-urlencoded-parser + // Note that streaming decoder is stateful and cannot be reused + const streamingDecoder = new TextDecoder('utf-8', { ignoreBOM: true }) + + for await (const chunk of consumeBody(this[kState].body)) { + if (!isUint8Array(chunk)) { + throw new TypeError('Expected Uint8Array chunk') + } + text += streamingDecoder.decode(chunk, { stream: true }) + } + text += streamingDecoder.decode() + entries = new URLSearchParams(text) + } catch (err) { + // istanbul ignore next: Unclear when new URLSearchParams can fail on a string. + // 2. If entries is failure, then throw a TypeError. + throw Object.assign(new TypeError(), { cause: err }) + } + + // 3. Return a new FormData object whose entries are entries. + const formData = new FormData() + for (const [name, value] of entries) { + formData.append(name, value) + } + return formData + } else { + // Wait a tick before checking if the request has been aborted. + // Otherwise, a TypeError can be thrown when an AbortError should. + await Promise.resolve() + + throwIfAborted(this[kState]) + + // Otherwise, throw a TypeError. + throw webidl.errors.exception({ + header: `${instance.name}.formData`, + message: 'Could not parse content as FormData.' + }) + } + } + } + + return methods +} + +function mixinBody (prototype) { + Object.assign(prototype.prototype, bodyMixinMethods(prototype)) +} + +/** + * @see https://fetch.spec.whatwg.org/#concept-body-consume-body + * @param {Response|Request} object + * @param {(value: unknown) => unknown} convertBytesToJSValue + * @param {Response|Request} instance + */ +async function specConsumeBody (object, convertBytesToJSValue, instance) { + webidl.brandCheck(object, instance) + + throwIfAborted(object[kState]) + + // 1. If object is unusable, then return a promise rejected + // with a TypeError. + if (bodyUnusable(object[kState].body)) { + throw new TypeError('Body is unusable') + } + + // 2. Let promise be a new promise. + const promise = createDeferredPromise() + + // 3. Let errorSteps given error be to reject promise with error. + const errorSteps = (error) => promise.reject(error) + + // 4. Let successSteps given a byte sequence data be to resolve + // promise with the result of running convertBytesToJSValue + // with data. If that threw an exception, then run errorSteps + // with that exception. + const successSteps = (data) => { + try { + promise.resolve(convertBytesToJSValue(data)) + } catch (e) { + errorSteps(e) + } + } + + // 5. If object’s body is null, then run successSteps with an + // empty byte sequence. + if (object[kState].body == null) { + successSteps(new Uint8Array()) + return promise.promise + } + + // 6. Otherwise, fully read object’s body given successSteps, + // errorSteps, and object’s relevant global object. + await fullyReadBody(object[kState].body, successSteps, errorSteps) + + // 7. Return promise. + return promise.promise +} + +// https://fetch.spec.whatwg.org/#body-unusable +function bodyUnusable (body) { + // An object including the Body interface mixin is + // said to be unusable if its body is non-null and + // its body’s stream is disturbed or locked. + return body != null && (body.stream.locked || util.isDisturbed(body.stream)) +} + +/** + * @see https://encoding.spec.whatwg.org/#utf-8-decode + * @param {Buffer} buffer + */ +function utf8DecodeBytes (buffer) { + if (buffer.length === 0) { + return '' + } + + // 1. Let buffer be the result of peeking three bytes from + // ioQueue, converted to a byte sequence. + + // 2. If buffer is 0xEF 0xBB 0xBF, then read three + // bytes from ioQueue. (Do nothing with those bytes.) + if (buffer[0] === 0xEF && buffer[1] === 0xBB && buffer[2] === 0xBF) { + buffer = buffer.subarray(3) + } + + // 3. Process a queue with an instance of UTF-8’s + // decoder, ioQueue, output, and "replacement". + const output = textDecoder.decode(buffer) + + // 4. Return output. + return output +} + +/** + * @see https://infra.spec.whatwg.org/#parse-json-bytes-to-a-javascript-value + * @param {Uint8Array} bytes + */ +function parseJSONFromBytes (bytes) { + return JSON.parse(utf8DecodeBytes(bytes)) +} + +/** + * @see https://fetch.spec.whatwg.org/#concept-body-mime-type + * @param {import('./response').Response|import('./request').Request} object + */ +function bodyMimeType (object) { + const { headersList } = object[kState] + const contentType = headersList.get('content-type') + + if (contentType === null) { + return 'failure' + } + + return parseMIMEType(contentType) +} + +module.exports = { + extractBody, + safelyExtractBody, + cloneBody, + mixinBody +} + + +/***/ }), + +/***/ 7059: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { MessageChannel, receiveMessageOnPort } = __nccwpck_require__(1267) + +const corsSafeListedMethods = ['GET', 'HEAD', 'POST'] +const corsSafeListedMethodsSet = new Set(corsSafeListedMethods) + +const nullBodyStatus = [101, 204, 205, 304] + +const redirectStatus = [301, 302, 303, 307, 308] +const redirectStatusSet = new Set(redirectStatus) + +// https://fetch.spec.whatwg.org/#block-bad-port +const badPorts = [ + '1', '7', '9', '11', '13', '15', '17', '19', '20', '21', '22', '23', '25', '37', '42', '43', '53', '69', '77', '79', + '87', '95', '101', '102', '103', '104', '109', '110', '111', '113', '115', '117', '119', '123', '135', '137', + '139', '143', '161', '179', '389', '427', '465', '512', '513', '514', '515', '526', '530', '531', '532', + '540', '548', '554', '556', '563', '587', '601', '636', '989', '990', '993', '995', '1719', '1720', '1723', + '2049', '3659', '4045', '5060', '5061', '6000', '6566', '6665', '6666', '6667', '6668', '6669', '6697', + '10080' +] + +const badPortsSet = new Set(badPorts) + +// https://w3c.github.io/webappsec-referrer-policy/#referrer-policies +const referrerPolicy = [ + '', + 'no-referrer', + 'no-referrer-when-downgrade', + 'same-origin', + 'origin', + 'strict-origin', + 'origin-when-cross-origin', + 'strict-origin-when-cross-origin', + 'unsafe-url' +] +const referrerPolicySet = new Set(referrerPolicy) + +const requestRedirect = ['follow', 'manual', 'error'] + +const safeMethods = ['GET', 'HEAD', 'OPTIONS', 'TRACE'] +const safeMethodsSet = new Set(safeMethods) + +const requestMode = ['navigate', 'same-origin', 'no-cors', 'cors'] + +const requestCredentials = ['omit', 'same-origin', 'include'] + +const requestCache = [ + 'default', + 'no-store', + 'reload', + 'no-cache', + 'force-cache', + 'only-if-cached' +] + +// https://fetch.spec.whatwg.org/#request-body-header-name +const requestBodyHeader = [ + 'content-encoding', + 'content-language', + 'content-location', + 'content-type', + // See https://github.com/nodejs/undici/issues/2021 + // 'Content-Length' is a forbidden header name, which is typically + // removed in the Headers implementation. However, undici doesn't + // filter out headers, so we add it here. + 'content-length' +] + +// https://fetch.spec.whatwg.org/#enumdef-requestduplex +const requestDuplex = [ + 'half' +] + +// http://fetch.spec.whatwg.org/#forbidden-method +const forbiddenMethods = ['CONNECT', 'TRACE', 'TRACK'] +const forbiddenMethodsSet = new Set(forbiddenMethods) + +const subresource = [ + 'audio', + 'audioworklet', + 'font', + 'image', + 'manifest', + 'paintworklet', + 'script', + 'style', + 'track', + 'video', + 'xslt', + '' +] +const subresourceSet = new Set(subresource) + +/** @type {globalThis['DOMException']} */ +const DOMException = globalThis.DOMException ?? (() => { + // DOMException was only made a global in Node v17.0.0, + // but fetch supports >= v16.8. + try { + atob('~') + } catch (err) { + return Object.getPrototypeOf(err).constructor + } +})() + +let channel + +/** @type {globalThis['structuredClone']} */ +const structuredClone = + globalThis.structuredClone ?? + // https://github.com/nodejs/node/blob/b27ae24dcc4251bad726d9d84baf678d1f707fed/lib/internal/structured_clone.js + // structuredClone was added in v17.0.0, but fetch supports v16.8 + function structuredClone (value, options = undefined) { + if (arguments.length === 0) { + throw new TypeError('missing argument') + } + + if (!channel) { + channel = new MessageChannel() + } + channel.port1.unref() + channel.port2.unref() + channel.port1.postMessage(value, options?.transfer) + return receiveMessageOnPort(channel.port2).message + } + +module.exports = { + DOMException, + structuredClone, + subresource, + forbiddenMethods, + requestBodyHeader, + referrerPolicy, + requestRedirect, + requestMode, + requestCredentials, + requestCache, + redirectStatus, + corsSafeListedMethods, + nullBodyStatus, + safeMethods, + badPorts, + requestDuplex, + subresourceSet, + badPortsSet, + redirectStatusSet, + corsSafeListedMethodsSet, + safeMethodsSet, + forbiddenMethodsSet, + referrerPolicySet +} + + +/***/ }), + +/***/ 2791: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +const assert = __nccwpck_require__(9491) +const { atob } = __nccwpck_require__(4300) +const { isomorphicDecode } = __nccwpck_require__(784) + +const encoder = new TextEncoder() + +/** + * @see https://mimesniff.spec.whatwg.org/#http-token-code-point + */ +const HTTP_TOKEN_CODEPOINTS = /^[!#$%&'*+-.^_|~A-Za-z0-9]+$/ +const HTTP_WHITESPACE_REGEX = /(\u000A|\u000D|\u0009|\u0020)/ // eslint-disable-line +/** + * @see https://mimesniff.spec.whatwg.org/#http-quoted-string-token-code-point + */ +const HTTP_QUOTED_STRING_TOKENS = /[\u0009|\u0020-\u007E|\u0080-\u00FF]/ // eslint-disable-line + +// https://fetch.spec.whatwg.org/#data-url-processor +/** @param {URL} dataURL */ +function dataURLProcessor (dataURL) { + // 1. Assert: dataURL’s scheme is "data". + assert(dataURL.protocol === 'data:') + + // 2. Let input be the result of running the URL + // serializer on dataURL with exclude fragment + // set to true. + let input = URLSerializer(dataURL, true) + + // 3. Remove the leading "data:" string from input. + input = input.slice(5) + + // 4. Let position point at the start of input. + const position = { position: 0 } + + // 5. Let mimeType be the result of collecting a + // sequence of code points that are not equal + // to U+002C (,), given position. + let mimeType = collectASequenceOfCodePointsFast( + ',', + input, + position + ) + + // 6. Strip leading and trailing ASCII whitespace + // from mimeType. + // Undici implementation note: we need to store the + // length because if the mimetype has spaces removed, + // the wrong amount will be sliced from the input in + // step #9 + const mimeTypeLength = mimeType.length + mimeType = removeASCIIWhitespace(mimeType, true, true) + + // 7. If position is past the end of input, then + // return failure + if (position.position >= input.length) { + return 'failure' + } + + // 8. Advance position by 1. + position.position++ + + // 9. Let encodedBody be the remainder of input. + const encodedBody = input.slice(mimeTypeLength + 1) + + // 10. Let body be the percent-decoding of encodedBody. + let body = stringPercentDecode(encodedBody) + + // 11. If mimeType ends with U+003B (;), followed by + // zero or more U+0020 SPACE, followed by an ASCII + // case-insensitive match for "base64", then: + if (/;(\u0020){0,}base64$/i.test(mimeType)) { + // 1. Let stringBody be the isomorphic decode of body. + const stringBody = isomorphicDecode(body) + + // 2. Set body to the forgiving-base64 decode of + // stringBody. + body = forgivingBase64(stringBody) + + // 3. If body is failure, then return failure. + if (body === 'failure') { + return 'failure' + } + + // 4. Remove the last 6 code points from mimeType. + mimeType = mimeType.slice(0, -6) + + // 5. Remove trailing U+0020 SPACE code points from mimeType, + // if any. + mimeType = mimeType.replace(/(\u0020)+$/, '') + + // 6. Remove the last U+003B (;) code point from mimeType. + mimeType = mimeType.slice(0, -1) + } + + // 12. If mimeType starts with U+003B (;), then prepend + // "text/plain" to mimeType. + if (mimeType.startsWith(';')) { + mimeType = 'text/plain' + mimeType + } + + // 13. Let mimeTypeRecord be the result of parsing + // mimeType. + let mimeTypeRecord = parseMIMEType(mimeType) + + // 14. If mimeTypeRecord is failure, then set + // mimeTypeRecord to text/plain;charset=US-ASCII. + if (mimeTypeRecord === 'failure') { + mimeTypeRecord = parseMIMEType('text/plain;charset=US-ASCII') + } + + // 15. Return a new data: URL struct whose MIME + // type is mimeTypeRecord and body is body. + // https://fetch.spec.whatwg.org/#data-url-struct + return { mimeType: mimeTypeRecord, body } +} + +// https://url.spec.whatwg.org/#concept-url-serializer +/** + * @param {URL} url + * @param {boolean} excludeFragment + */ +function URLSerializer (url, excludeFragment = false) { + const href = url.href + + if (!excludeFragment) { + return href + } + + const hash = href.lastIndexOf('#') + if (hash === -1) { + return href + } + return href.slice(0, hash) +} + +// https://infra.spec.whatwg.org/#collect-a-sequence-of-code-points +/** + * @param {(char: string) => boolean} condition + * @param {string} input + * @param {{ position: number }} position + */ +function collectASequenceOfCodePoints (condition, input, position) { + // 1. Let result be the empty string. + let result = '' + + // 2. While position doesn’t point past the end of input and the + // code point at position within input meets the condition condition: + while (position.position < input.length && condition(input[position.position])) { + // 1. Append that code point to the end of result. + result += input[position.position] + + // 2. Advance position by 1. + position.position++ + } + + // 3. Return result. + return result +} + +/** + * A faster collectASequenceOfCodePoints that only works when comparing a single character. + * @param {string} char + * @param {string} input + * @param {{ position: number }} position + */ +function collectASequenceOfCodePointsFast (char, input, position) { + const idx = input.indexOf(char, position.position) + const start = position.position + + if (idx === -1) { + position.position = input.length + return input.slice(start) + } + + position.position = idx + return input.slice(start, position.position) +} + +// https://url.spec.whatwg.org/#string-percent-decode +/** @param {string} input */ +function stringPercentDecode (input) { + // 1. Let bytes be the UTF-8 encoding of input. + const bytes = encoder.encode(input) + + // 2. Return the percent-decoding of bytes. + return percentDecode(bytes) +} + +// https://url.spec.whatwg.org/#percent-decode +/** @param {Uint8Array} input */ +function percentDecode (input) { + // 1. Let output be an empty byte sequence. + /** @type {number[]} */ + const output = [] + + // 2. For each byte byte in input: + for (let i = 0; i < input.length; i++) { + const byte = input[i] + + // 1. If byte is not 0x25 (%), then append byte to output. + if (byte !== 0x25) { + output.push(byte) + + // 2. Otherwise, if byte is 0x25 (%) and the next two bytes + // after byte in input are not in the ranges + // 0x30 (0) to 0x39 (9), 0x41 (A) to 0x46 (F), + // and 0x61 (a) to 0x66 (f), all inclusive, append byte + // to output. + } else if ( + byte === 0x25 && + !/^[0-9A-Fa-f]{2}$/i.test(String.fromCharCode(input[i + 1], input[i + 2])) + ) { + output.push(0x25) + + // 3. Otherwise: + } else { + // 1. Let bytePoint be the two bytes after byte in input, + // decoded, and then interpreted as hexadecimal number. + const nextTwoBytes = String.fromCharCode(input[i + 1], input[i + 2]) + const bytePoint = Number.parseInt(nextTwoBytes, 16) + + // 2. Append a byte whose value is bytePoint to output. + output.push(bytePoint) + + // 3. Skip the next two bytes in input. + i += 2 + } + } + + // 3. Return output. + return Uint8Array.from(output) +} + +// https://mimesniff.spec.whatwg.org/#parse-a-mime-type +/** @param {string} input */ +function parseMIMEType (input) { + // 1. Remove any leading and trailing HTTP whitespace + // from input. + input = removeHTTPWhitespace(input, true, true) + + // 2. Let position be a position variable for input, + // initially pointing at the start of input. + const position = { position: 0 } + + // 3. Let type be the result of collecting a sequence + // of code points that are not U+002F (/) from + // input, given position. + const type = collectASequenceOfCodePointsFast( + '/', + input, + position + ) + + // 4. If type is the empty string or does not solely + // contain HTTP token code points, then return failure. + // https://mimesniff.spec.whatwg.org/#http-token-code-point + if (type.length === 0 || !HTTP_TOKEN_CODEPOINTS.test(type)) { + return 'failure' + } + + // 5. If position is past the end of input, then return + // failure + if (position.position > input.length) { + return 'failure' + } + + // 6. Advance position by 1. (This skips past U+002F (/).) + position.position++ + + // 7. Let subtype be the result of collecting a sequence of + // code points that are not U+003B (;) from input, given + // position. + let subtype = collectASequenceOfCodePointsFast( + ';', + input, + position + ) + + // 8. Remove any trailing HTTP whitespace from subtype. + subtype = removeHTTPWhitespace(subtype, false, true) + + // 9. If subtype is the empty string or does not solely + // contain HTTP token code points, then return failure. + if (subtype.length === 0 || !HTTP_TOKEN_CODEPOINTS.test(subtype)) { + return 'failure' + } + + const typeLowercase = type.toLowerCase() + const subtypeLowercase = subtype.toLowerCase() + + // 10. Let mimeType be a new MIME type record whose type + // is type, in ASCII lowercase, and subtype is subtype, + // in ASCII lowercase. + // https://mimesniff.spec.whatwg.org/#mime-type + const mimeType = { + type: typeLowercase, + subtype: subtypeLowercase, + /** @type {Map} */ + parameters: new Map(), + // https://mimesniff.spec.whatwg.org/#mime-type-essence + essence: `${typeLowercase}/${subtypeLowercase}` + } + + // 11. While position is not past the end of input: + while (position.position < input.length) { + // 1. Advance position by 1. (This skips past U+003B (;).) + position.position++ + + // 2. Collect a sequence of code points that are HTTP + // whitespace from input given position. + collectASequenceOfCodePoints( + // https://fetch.spec.whatwg.org/#http-whitespace + char => HTTP_WHITESPACE_REGEX.test(char), + input, + position + ) + + // 3. Let parameterName be the result of collecting a + // sequence of code points that are not U+003B (;) + // or U+003D (=) from input, given position. + let parameterName = collectASequenceOfCodePoints( + (char) => char !== ';' && char !== '=', + input, + position + ) + + // 4. Set parameterName to parameterName, in ASCII + // lowercase. + parameterName = parameterName.toLowerCase() + + // 5. If position is not past the end of input, then: + if (position.position < input.length) { + // 1. If the code point at position within input is + // U+003B (;), then continue. + if (input[position.position] === ';') { + continue + } + + // 2. Advance position by 1. (This skips past U+003D (=).) + position.position++ + } + + // 6. If position is past the end of input, then break. + if (position.position > input.length) { + break + } + + // 7. Let parameterValue be null. + let parameterValue = null + + // 8. If the code point at position within input is + // U+0022 ("), then: + if (input[position.position] === '"') { + // 1. Set parameterValue to the result of collecting + // an HTTP quoted string from input, given position + // and the extract-value flag. + parameterValue = collectAnHTTPQuotedString(input, position, true) + + // 2. Collect a sequence of code points that are not + // U+003B (;) from input, given position. + collectASequenceOfCodePointsFast( + ';', + input, + position + ) + + // 9. Otherwise: + } else { + // 1. Set parameterValue to the result of collecting + // a sequence of code points that are not U+003B (;) + // from input, given position. + parameterValue = collectASequenceOfCodePointsFast( + ';', + input, + position + ) + + // 2. Remove any trailing HTTP whitespace from parameterValue. + parameterValue = removeHTTPWhitespace(parameterValue, false, true) + + // 3. If parameterValue is the empty string, then continue. + if (parameterValue.length === 0) { + continue + } + } + + // 10. If all of the following are true + // - parameterName is not the empty string + // - parameterName solely contains HTTP token code points + // - parameterValue solely contains HTTP quoted-string token code points + // - mimeType’s parameters[parameterName] does not exist + // then set mimeType’s parameters[parameterName] to parameterValue. + if ( + parameterName.length !== 0 && + HTTP_TOKEN_CODEPOINTS.test(parameterName) && + (parameterValue.length === 0 || HTTP_QUOTED_STRING_TOKENS.test(parameterValue)) && + !mimeType.parameters.has(parameterName) + ) { + mimeType.parameters.set(parameterName, parameterValue) + } + } + + // 12. Return mimeType. + return mimeType +} + +// https://infra.spec.whatwg.org/#forgiving-base64-decode +/** @param {string} data */ +function forgivingBase64 (data) { + // 1. Remove all ASCII whitespace from data. + data = data.replace(/[\u0009\u000A\u000C\u000D\u0020]/g, '') // eslint-disable-line + + // 2. If data’s code point length divides by 4 leaving + // no remainder, then: + if (data.length % 4 === 0) { + // 1. If data ends with one or two U+003D (=) code points, + // then remove them from data. + data = data.replace(/=?=$/, '') + } + + // 3. If data’s code point length divides by 4 leaving + // a remainder of 1, then return failure. + if (data.length % 4 === 1) { + return 'failure' + } + + // 4. If data contains a code point that is not one of + // U+002B (+) + // U+002F (/) + // ASCII alphanumeric + // then return failure. + if (/[^+/0-9A-Za-z]/.test(data)) { + return 'failure' + } + + const binary = atob(data) + const bytes = new Uint8Array(binary.length) + + for (let byte = 0; byte < binary.length; byte++) { + bytes[byte] = binary.charCodeAt(byte) + } + + return bytes +} + +// https://fetch.spec.whatwg.org/#collect-an-http-quoted-string +// tests: https://fetch.spec.whatwg.org/#example-http-quoted-string +/** + * @param {string} input + * @param {{ position: number }} position + * @param {boolean?} extractValue + */ +function collectAnHTTPQuotedString (input, position, extractValue) { + // 1. Let positionStart be position. + const positionStart = position.position + + // 2. Let value be the empty string. + let value = '' + + // 3. Assert: the code point at position within input + // is U+0022 ("). + assert(input[position.position] === '"') + + // 4. Advance position by 1. + position.position++ + + // 5. While true: + while (true) { + // 1. Append the result of collecting a sequence of code points + // that are not U+0022 (") or U+005C (\) from input, given + // position, to value. + value += collectASequenceOfCodePoints( + (char) => char !== '"' && char !== '\\', + input, + position + ) + + // 2. If position is past the end of input, then break. + if (position.position >= input.length) { + break + } + + // 3. Let quoteOrBackslash be the code point at position within + // input. + const quoteOrBackslash = input[position.position] + + // 4. Advance position by 1. + position.position++ + + // 5. If quoteOrBackslash is U+005C (\), then: + if (quoteOrBackslash === '\\') { + // 1. If position is past the end of input, then append + // U+005C (\) to value and break. + if (position.position >= input.length) { + value += '\\' + break + } + + // 2. Append the code point at position within input to value. + value += input[position.position] + + // 3. Advance position by 1. + position.position++ + + // 6. Otherwise: + } else { + // 1. Assert: quoteOrBackslash is U+0022 ("). + assert(quoteOrBackslash === '"') + + // 2. Break. + break + } + } + + // 6. If the extract-value flag is set, then return value. + if (extractValue) { + return value + } + + // 7. Return the code points from positionStart to position, + // inclusive, within input. + return input.slice(positionStart, position.position) +} + +/** + * @see https://mimesniff.spec.whatwg.org/#serialize-a-mime-type + */ +function serializeAMimeType (mimeType) { + assert(mimeType !== 'failure') + const { parameters, essence } = mimeType + + // 1. Let serialization be the concatenation of mimeType’s + // type, U+002F (/), and mimeType’s subtype. + let serialization = essence + + // 2. For each name → value of mimeType’s parameters: + for (let [name, value] of parameters.entries()) { + // 1. Append U+003B (;) to serialization. + serialization += ';' + + // 2. Append name to serialization. + serialization += name + + // 3. Append U+003D (=) to serialization. + serialization += '=' + + // 4. If value does not solely contain HTTP token code + // points or value is the empty string, then: + if (!HTTP_TOKEN_CODEPOINTS.test(value)) { + // 1. Precede each occurence of U+0022 (") or + // U+005C (\) in value with U+005C (\). + value = value.replace(/(\\|")/g, '\\$1') + + // 2. Prepend U+0022 (") to value. + value = '"' + value + + // 3. Append U+0022 (") to value. + value += '"' + } + + // 5. Append value to serialization. + serialization += value + } + + // 3. Return serialization. + return serialization +} + +/** + * @see https://fetch.spec.whatwg.org/#http-whitespace + * @param {string} char + */ +function isHTTPWhiteSpace (char) { + return char === '\r' || char === '\n' || char === '\t' || char === ' ' +} + +/** + * @see https://fetch.spec.whatwg.org/#http-whitespace + * @param {string} str + */ +function removeHTTPWhitespace (str, leading = true, trailing = true) { + let lead = 0 + let trail = str.length - 1 + + if (leading) { + for (; lead < str.length && isHTTPWhiteSpace(str[lead]); lead++); + } + + if (trailing) { + for (; trail > 0 && isHTTPWhiteSpace(str[trail]); trail--); + } + + return str.slice(lead, trail + 1) +} + +/** + * @see https://infra.spec.whatwg.org/#ascii-whitespace + * @param {string} char + */ +function isASCIIWhitespace (char) { + return char === '\r' || char === '\n' || char === '\t' || char === '\f' || char === ' ' +} + +/** + * @see https://infra.spec.whatwg.org/#strip-leading-and-trailing-ascii-whitespace + */ +function removeASCIIWhitespace (str, leading = true, trailing = true) { + let lead = 0 + let trail = str.length - 1 + + if (leading) { + for (; lead < str.length && isASCIIWhitespace(str[lead]); lead++); + } + + if (trailing) { + for (; trail > 0 && isASCIIWhitespace(str[trail]); trail--); + } + + return str.slice(lead, trail + 1) +} + +module.exports = { + dataURLProcessor, + URLSerializer, + collectASequenceOfCodePoints, + collectASequenceOfCodePointsFast, + stringPercentDecode, + parseMIMEType, + collectAnHTTPQuotedString, + serializeAMimeType +} + + +/***/ }), + +/***/ 5479: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { Blob, File: NativeFile } = __nccwpck_require__(4300) +const { types } = __nccwpck_require__(3837) +const { kState } = __nccwpck_require__(8085) +const { isBlobLike } = __nccwpck_require__(784) +const { webidl } = __nccwpck_require__(1537) +const { parseMIMEType, serializeAMimeType } = __nccwpck_require__(2791) +const { kEnumerableProperty } = __nccwpck_require__(9522) +const encoder = new TextEncoder() + +class File extends Blob { + constructor (fileBits, fileName, options = {}) { + // The File constructor is invoked with two or three parameters, depending + // on whether the optional dictionary parameter is used. When the File() + // constructor is invoked, user agents must run the following steps: + webidl.argumentLengthCheck(arguments, 2, { header: 'File constructor' }) + + fileBits = webidl.converters['sequence'](fileBits) + fileName = webidl.converters.USVString(fileName) + options = webidl.converters.FilePropertyBag(options) + + // 1. Let bytes be the result of processing blob parts given fileBits and + // options. + // Note: Blob handles this for us + + // 2. Let n be the fileName argument to the constructor. + const n = fileName + + // 3. Process FilePropertyBag dictionary argument by running the following + // substeps: + + // 1. If the type member is provided and is not the empty string, let t + // be set to the type dictionary member. If t contains any characters + // outside the range U+0020 to U+007E, then set t to the empty string + // and return from these substeps. + // 2. Convert every character in t to ASCII lowercase. + let t = options.type + let d + + // eslint-disable-next-line no-labels + substep: { + if (t) { + t = parseMIMEType(t) + + if (t === 'failure') { + t = '' + // eslint-disable-next-line no-labels + break substep + } + + t = serializeAMimeType(t).toLowerCase() + } + + // 3. If the lastModified member is provided, let d be set to the + // lastModified dictionary member. If it is not provided, set d to the + // current date and time represented as the number of milliseconds since + // the Unix Epoch (which is the equivalent of Date.now() [ECMA-262]). + d = options.lastModified + } + + // 4. Return a new File object F such that: + // F refers to the bytes byte sequence. + // F.size is set to the number of total bytes in bytes. + // F.name is set to n. + // F.type is set to t. + // F.lastModified is set to d. + + super(processBlobParts(fileBits, options), { type: t }) + this[kState] = { + name: n, + lastModified: d, + type: t + } + } + + get name () { + webidl.brandCheck(this, File) + + return this[kState].name + } + + get lastModified () { + webidl.brandCheck(this, File) + + return this[kState].lastModified + } + + get type () { + webidl.brandCheck(this, File) + + return this[kState].type + } +} + +class FileLike { + constructor (blobLike, fileName, options = {}) { + // TODO: argument idl type check + + // The File constructor is invoked with two or three parameters, depending + // on whether the optional dictionary parameter is used. When the File() + // constructor is invoked, user agents must run the following steps: + + // 1. Let bytes be the result of processing blob parts given fileBits and + // options. + + // 2. Let n be the fileName argument to the constructor. + const n = fileName + + // 3. Process FilePropertyBag dictionary argument by running the following + // substeps: + + // 1. If the type member is provided and is not the empty string, let t + // be set to the type dictionary member. If t contains any characters + // outside the range U+0020 to U+007E, then set t to the empty string + // and return from these substeps. + // TODO + const t = options.type + + // 2. Convert every character in t to ASCII lowercase. + // TODO + + // 3. If the lastModified member is provided, let d be set to the + // lastModified dictionary member. If it is not provided, set d to the + // current date and time represented as the number of milliseconds since + // the Unix Epoch (which is the equivalent of Date.now() [ECMA-262]). + const d = options.lastModified ?? Date.now() + + // 4. Return a new File object F such that: + // F refers to the bytes byte sequence. + // F.size is set to the number of total bytes in bytes. + // F.name is set to n. + // F.type is set to t. + // F.lastModified is set to d. + + this[kState] = { + blobLike, + name: n, + type: t, + lastModified: d + } + } + + stream (...args) { + webidl.brandCheck(this, FileLike) + + return this[kState].blobLike.stream(...args) + } + + arrayBuffer (...args) { + webidl.brandCheck(this, FileLike) + + return this[kState].blobLike.arrayBuffer(...args) + } + + slice (...args) { + webidl.brandCheck(this, FileLike) + + return this[kState].blobLike.slice(...args) + } + + text (...args) { + webidl.brandCheck(this, FileLike) + + return this[kState].blobLike.text(...args) + } + + get size () { + webidl.brandCheck(this, FileLike) + + return this[kState].blobLike.size + } + + get type () { + webidl.brandCheck(this, FileLike) + + return this[kState].blobLike.type + } + + get name () { + webidl.brandCheck(this, FileLike) + + return this[kState].name + } + + get lastModified () { + webidl.brandCheck(this, FileLike) + + return this[kState].lastModified + } + + get [Symbol.toStringTag] () { + return 'File' + } +} + +Object.defineProperties(File.prototype, { + [Symbol.toStringTag]: { + value: 'File', + configurable: true + }, + name: kEnumerableProperty, + lastModified: kEnumerableProperty +}) + +webidl.converters.Blob = webidl.interfaceConverter(Blob) + +webidl.converters.BlobPart = function (V, opts) { + if (webidl.util.Type(V) === 'Object') { + if (isBlobLike(V)) { + return webidl.converters.Blob(V, { strict: false }) + } + + if ( + ArrayBuffer.isView(V) || + types.isAnyArrayBuffer(V) + ) { + return webidl.converters.BufferSource(V, opts) + } + } + + return webidl.converters.USVString(V, opts) +} + +webidl.converters['sequence'] = webidl.sequenceConverter( + webidl.converters.BlobPart +) + +// https://www.w3.org/TR/FileAPI/#dfn-FilePropertyBag +webidl.converters.FilePropertyBag = webidl.dictionaryConverter([ + { + key: 'lastModified', + converter: webidl.converters['long long'], + get defaultValue () { + return Date.now() + } + }, + { + key: 'type', + converter: webidl.converters.DOMString, + defaultValue: '' + }, + { + key: 'endings', + converter: (value) => { + value = webidl.converters.DOMString(value) + value = value.toLowerCase() + + if (value !== 'native') { + value = 'transparent' + } + + return value + }, + defaultValue: 'transparent' + } +]) + +/** + * @see https://www.w3.org/TR/FileAPI/#process-blob-parts + * @param {(NodeJS.TypedArray|Blob|string)[]} parts + * @param {{ type: string, endings: string }} options + */ +function processBlobParts (parts, options) { + // 1. Let bytes be an empty sequence of bytes. + /** @type {NodeJS.TypedArray[]} */ + const bytes = [] + + // 2. For each element in parts: + for (const element of parts) { + // 1. If element is a USVString, run the following substeps: + if (typeof element === 'string') { + // 1. Let s be element. + let s = element + + // 2. If the endings member of options is "native", set s + // to the result of converting line endings to native + // of element. + if (options.endings === 'native') { + s = convertLineEndingsNative(s) + } + + // 3. Append the result of UTF-8 encoding s to bytes. + bytes.push(encoder.encode(s)) + } else if ( + types.isAnyArrayBuffer(element) || + types.isTypedArray(element) + ) { + // 2. If element is a BufferSource, get a copy of the + // bytes held by the buffer source, and append those + // bytes to bytes. + if (!element.buffer) { // ArrayBuffer + bytes.push(new Uint8Array(element)) + } else { + bytes.push( + new Uint8Array(element.buffer, element.byteOffset, element.byteLength) + ) + } + } else if (isBlobLike(element)) { + // 3. If element is a Blob, append the bytes it represents + // to bytes. + bytes.push(element) + } + } + + // 3. Return bytes. + return bytes +} + +/** + * @see https://www.w3.org/TR/FileAPI/#convert-line-endings-to-native + * @param {string} s + */ +function convertLineEndingsNative (s) { + // 1. Let native line ending be be the code point U+000A LF. + let nativeLineEnding = '\n' + + // 2. If the underlying platform’s conventions are to + // represent newlines as a carriage return and line feed + // sequence, set native line ending to the code point + // U+000D CR followed by the code point U+000A LF. + if (process.platform === 'win32') { + nativeLineEnding = '\r\n' + } + + return s.replace(/\r?\n/g, nativeLineEnding) +} + +// If this function is moved to ./util.js, some tools (such as +// rollup) will warn about circular dependencies. See: +// https://github.com/nodejs/undici/issues/1629 +function isFileLike (object) { + return ( + (NativeFile && object instanceof NativeFile) || + object instanceof File || ( + object && + (typeof object.stream === 'function' || + typeof object.arrayBuffer === 'function') && + object[Symbol.toStringTag] === 'File' + ) + ) +} + +module.exports = { File, FileLike, isFileLike } + + +/***/ }), + +/***/ 968: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { isBlobLike, toUSVString, makeIterator } = __nccwpck_require__(784) +const { kState } = __nccwpck_require__(8085) +const { File: UndiciFile, FileLike, isFileLike } = __nccwpck_require__(5479) +const { webidl } = __nccwpck_require__(1537) +const { Blob, File: NativeFile } = __nccwpck_require__(4300) + +/** @type {globalThis['File']} */ +const File = NativeFile ?? UndiciFile + +// https://xhr.spec.whatwg.org/#formdata +class FormData { + constructor (form) { + if (form !== undefined) { + throw webidl.errors.conversionFailed({ + prefix: 'FormData constructor', + argument: 'Argument 1', + types: ['undefined'] + }) + } + + this[kState] = [] + } + + append (name, value, filename = undefined) { + webidl.brandCheck(this, FormData) + + webidl.argumentLengthCheck(arguments, 2, { header: 'FormData.append' }) + + if (arguments.length === 3 && !isBlobLike(value)) { + throw new TypeError( + "Failed to execute 'append' on 'FormData': parameter 2 is not of type 'Blob'" + ) + } + + // 1. Let value be value if given; otherwise blobValue. + + name = webidl.converters.USVString(name) + value = isBlobLike(value) + ? webidl.converters.Blob(value, { strict: false }) + : webidl.converters.USVString(value) + filename = arguments.length === 3 + ? webidl.converters.USVString(filename) + : undefined + + // 2. Let entry be the result of creating an entry with + // name, value, and filename if given. + const entry = makeEntry(name, value, filename) + + // 3. Append entry to this’s entry list. + this[kState].push(entry) + } + + delete (name) { + webidl.brandCheck(this, FormData) + + webidl.argumentLengthCheck(arguments, 1, { header: 'FormData.delete' }) + + name = webidl.converters.USVString(name) + + // The delete(name) method steps are to remove all entries whose name + // is name from this’s entry list. + this[kState] = this[kState].filter(entry => entry.name !== name) + } + + get (name) { + webidl.brandCheck(this, FormData) + + webidl.argumentLengthCheck(arguments, 1, { header: 'FormData.get' }) + + name = webidl.converters.USVString(name) + + // 1. If there is no entry whose name is name in this’s entry list, + // then return null. + const idx = this[kState].findIndex((entry) => entry.name === name) + if (idx === -1) { + return null + } + + // 2. Return the value of the first entry whose name is name from + // this’s entry list. + return this[kState][idx].value + } + + getAll (name) { + webidl.brandCheck(this, FormData) + + webidl.argumentLengthCheck(arguments, 1, { header: 'FormData.getAll' }) + + name = webidl.converters.USVString(name) + + // 1. If there is no entry whose name is name in this’s entry list, + // then return the empty list. + // 2. Return the values of all entries whose name is name, in order, + // from this’s entry list. + return this[kState] + .filter((entry) => entry.name === name) + .map((entry) => entry.value) + } + + has (name) { + webidl.brandCheck(this, FormData) + + webidl.argumentLengthCheck(arguments, 1, { header: 'FormData.has' }) + + name = webidl.converters.USVString(name) + + // The has(name) method steps are to return true if there is an entry + // whose name is name in this’s entry list; otherwise false. + return this[kState].findIndex((entry) => entry.name === name) !== -1 + } + + set (name, value, filename = undefined) { + webidl.brandCheck(this, FormData) + + webidl.argumentLengthCheck(arguments, 2, { header: 'FormData.set' }) + + if (arguments.length === 3 && !isBlobLike(value)) { + throw new TypeError( + "Failed to execute 'set' on 'FormData': parameter 2 is not of type 'Blob'" + ) + } + + // The set(name, value) and set(name, blobValue, filename) method steps + // are: + + // 1. Let value be value if given; otherwise blobValue. + + name = webidl.converters.USVString(name) + value = isBlobLike(value) + ? webidl.converters.Blob(value, { strict: false }) + : webidl.converters.USVString(value) + filename = arguments.length === 3 + ? toUSVString(filename) + : undefined + + // 2. Let entry be the result of creating an entry with name, value, and + // filename if given. + const entry = makeEntry(name, value, filename) + + // 3. If there are entries in this’s entry list whose name is name, then + // replace the first such entry with entry and remove the others. + const idx = this[kState].findIndex((entry) => entry.name === name) + if (idx !== -1) { + this[kState] = [ + ...this[kState].slice(0, idx), + entry, + ...this[kState].slice(idx + 1).filter((entry) => entry.name !== name) + ] + } else { + // 4. Otherwise, append entry to this’s entry list. + this[kState].push(entry) + } + } + + entries () { + webidl.brandCheck(this, FormData) + + return makeIterator( + () => this[kState].map(pair => [pair.name, pair.value]), + 'FormData', + 'key+value' + ) + } + + keys () { + webidl.brandCheck(this, FormData) + + return makeIterator( + () => this[kState].map(pair => [pair.name, pair.value]), + 'FormData', + 'key' + ) + } + + values () { + webidl.brandCheck(this, FormData) + + return makeIterator( + () => this[kState].map(pair => [pair.name, pair.value]), + 'FormData', + 'value' + ) + } + + /** + * @param {(value: string, key: string, self: FormData) => void} callbackFn + * @param {unknown} thisArg + */ + forEach (callbackFn, thisArg = globalThis) { + webidl.brandCheck(this, FormData) + + webidl.argumentLengthCheck(arguments, 1, { header: 'FormData.forEach' }) + + if (typeof callbackFn !== 'function') { + throw new TypeError( + "Failed to execute 'forEach' on 'FormData': parameter 1 is not of type 'Function'." + ) + } + + for (const [key, value] of this) { + callbackFn.apply(thisArg, [value, key, this]) + } + } +} + +FormData.prototype[Symbol.iterator] = FormData.prototype.entries + +Object.defineProperties(FormData.prototype, { + [Symbol.toStringTag]: { + value: 'FormData', + configurable: true + } +}) + +/** + * @see https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#create-an-entry + * @param {string} name + * @param {string|Blob} value + * @param {?string} filename + * @returns + */ +function makeEntry (name, value, filename) { + // 1. Set name to the result of converting name into a scalar value string. + // "To convert a string into a scalar value string, replace any surrogates + // with U+FFFD." + // see: https://nodejs.org/dist/latest-v18.x/docs/api/buffer.html#buftostringencoding-start-end + name = Buffer.from(name).toString('utf8') + + // 2. If value is a string, then set value to the result of converting + // value into a scalar value string. + if (typeof value === 'string') { + value = Buffer.from(value).toString('utf8') + } else { + // 3. Otherwise: + + // 1. If value is not a File object, then set value to a new File object, + // representing the same bytes, whose name attribute value is "blob" + if (!isFileLike(value)) { + value = value instanceof Blob + ? new File([value], 'blob', { type: value.type }) + : new FileLike(value, 'blob', { type: value.type }) + } + + // 2. If filename is given, then set value to a new File object, + // representing the same bytes, whose name attribute is filename. + if (filename !== undefined) { + /** @type {FilePropertyBag} */ + const options = { + type: value.type, + lastModified: value.lastModified + } + + value = (NativeFile && value instanceof NativeFile) || value instanceof UndiciFile + ? new File([value], filename, options) + : new FileLike(value, filename, options) + } + } + + // 4. Return an entry whose name is name and whose value is value. + return { name, value } +} + +module.exports = { FormData } + + +/***/ }), + +/***/ 5799: +/***/ ((module) => { + +"use strict"; + + +// In case of breaking changes, increase the version +// number to avoid conflicts. +const globalOrigin = Symbol.for('undici.globalOrigin.1') + +function getGlobalOrigin () { + return globalThis[globalOrigin] +} + +function setGlobalOrigin (newOrigin) { + if (newOrigin === undefined) { + Object.defineProperty(globalThis, globalOrigin, { + value: undefined, + writable: true, + enumerable: false, + configurable: false + }) + + return + } + + const parsedURL = new URL(newOrigin) + + if (parsedURL.protocol !== 'http:' && parsedURL.protocol !== 'https:') { + throw new TypeError(`Only http & https urls are allowed, received ${parsedURL.protocol}`) + } + + Object.defineProperty(globalThis, globalOrigin, { + value: parsedURL, + writable: true, + enumerable: false, + configurable: false + }) +} + +module.exports = { + getGlobalOrigin, + setGlobalOrigin +} + + +/***/ }), + +/***/ 7689: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; +// https://github.com/Ethan-Arrowood/undici-fetch + + + +const { kHeadersList } = __nccwpck_require__(9440) +const { kGuard } = __nccwpck_require__(8085) +const { kEnumerableProperty } = __nccwpck_require__(9522) +const { + makeIterator, + isValidHeaderName, + isValidHeaderValue +} = __nccwpck_require__(784) +const { webidl } = __nccwpck_require__(1537) +const assert = __nccwpck_require__(9491) + +const kHeadersMap = Symbol('headers map') +const kHeadersSortedMap = Symbol('headers map sorted') + +/** + * @param {number} code + */ +function isHTTPWhiteSpaceCharCode (code) { + return code === 0x00a || code === 0x00d || code === 0x009 || code === 0x020 +} + +/** + * @see https://fetch.spec.whatwg.org/#concept-header-value-normalize + * @param {string} potentialValue + */ +function headerValueNormalize (potentialValue) { + // To normalize a byte sequence potentialValue, remove + // any leading and trailing HTTP whitespace bytes from + // potentialValue. + let i = 0; let j = potentialValue.length + + while (j > i && isHTTPWhiteSpaceCharCode(potentialValue.charCodeAt(j - 1))) --j + while (j > i && isHTTPWhiteSpaceCharCode(potentialValue.charCodeAt(i))) ++i + + return i === 0 && j === potentialValue.length ? potentialValue : potentialValue.substring(i, j) +} + +function fill (headers, object) { + // To fill a Headers object headers with a given object object, run these steps: + + // 1. If object is a sequence, then for each header in object: + // Note: webidl conversion to array has already been done. + if (Array.isArray(object)) { + for (let i = 0; i < object.length; ++i) { + const header = object[i] + // 1. If header does not contain exactly two items, then throw a TypeError. + if (header.length !== 2) { + throw webidl.errors.exception({ + header: 'Headers constructor', + message: `expected name/value pair to be length 2, found ${header.length}.` + }) + } + + // 2. Append (header’s first item, header’s second item) to headers. + appendHeader(headers, header[0], header[1]) + } + } else if (typeof object === 'object' && object !== null) { + // Note: null should throw + + // 2. Otherwise, object is a record, then for each key → value in object, + // append (key, value) to headers + const keys = Object.keys(object) + for (let i = 0; i < keys.length; ++i) { + appendHeader(headers, keys[i], object[keys[i]]) + } + } else { + throw webidl.errors.conversionFailed({ + prefix: 'Headers constructor', + argument: 'Argument 1', + types: ['sequence>', 'record'] + }) + } +} + +/** + * @see https://fetch.spec.whatwg.org/#concept-headers-append + */ +function appendHeader (headers, name, value) { + // 1. Normalize value. + value = headerValueNormalize(value) + + // 2. If name is not a header name or value is not a + // header value, then throw a TypeError. + if (!isValidHeaderName(name)) { + throw webidl.errors.invalidArgument({ + prefix: 'Headers.append', + value: name, + type: 'header name' + }) + } else if (!isValidHeaderValue(value)) { + throw webidl.errors.invalidArgument({ + prefix: 'Headers.append', + value, + type: 'header value' + }) + } + + // 3. If headers’s guard is "immutable", then throw a TypeError. + // 4. Otherwise, if headers’s guard is "request" and name is a + // forbidden header name, return. + // Note: undici does not implement forbidden header names + if (headers[kGuard] === 'immutable') { + throw new TypeError('immutable') + } else if (headers[kGuard] === 'request-no-cors') { + // 5. Otherwise, if headers’s guard is "request-no-cors": + // TODO + } + + // 6. Otherwise, if headers’s guard is "response" and name is a + // forbidden response-header name, return. + + // 7. Append (name, value) to headers’s header list. + return headers[kHeadersList].append(name, value) + + // 8. If headers’s guard is "request-no-cors", then remove + // privileged no-CORS request headers from headers +} + +class HeadersList { + /** @type {[string, string][]|null} */ + cookies = null + + constructor (init) { + if (init instanceof HeadersList) { + this[kHeadersMap] = new Map(init[kHeadersMap]) + this[kHeadersSortedMap] = init[kHeadersSortedMap] + this.cookies = init.cookies === null ? null : [...init.cookies] + } else { + this[kHeadersMap] = new Map(init) + this[kHeadersSortedMap] = null + } + } + + // https://fetch.spec.whatwg.org/#header-list-contains + contains (name) { + // A header list list contains a header name name if list + // contains a header whose name is a byte-case-insensitive + // match for name. + name = name.toLowerCase() + + return this[kHeadersMap].has(name) + } + + clear () { + this[kHeadersMap].clear() + this[kHeadersSortedMap] = null + this.cookies = null + } + + // https://fetch.spec.whatwg.org/#concept-header-list-append + append (name, value) { + this[kHeadersSortedMap] = null + + // 1. If list contains name, then set name to the first such + // header’s name. + const lowercaseName = name.toLowerCase() + const exists = this[kHeadersMap].get(lowercaseName) + + // 2. Append (name, value) to list. + if (exists) { + const delimiter = lowercaseName === 'cookie' ? '; ' : ', ' + this[kHeadersMap].set(lowercaseName, { + name: exists.name, + value: `${exists.value}${delimiter}${value}` + }) + } else { + this[kHeadersMap].set(lowercaseName, { name, value }) + } + + if (lowercaseName === 'set-cookie') { + this.cookies ??= [] + this.cookies.push(value) + } + } + + // https://fetch.spec.whatwg.org/#concept-header-list-set + set (name, value) { + this[kHeadersSortedMap] = null + const lowercaseName = name.toLowerCase() + + if (lowercaseName === 'set-cookie') { + this.cookies = [value] + } + + // 1. If list contains name, then set the value of + // the first such header to value and remove the + // others. + // 2. Otherwise, append header (name, value) to list. + this[kHeadersMap].set(lowercaseName, { name, value }) + } + + // https://fetch.spec.whatwg.org/#concept-header-list-delete + delete (name) { + this[kHeadersSortedMap] = null + + name = name.toLowerCase() + + if (name === 'set-cookie') { + this.cookies = null + } + + this[kHeadersMap].delete(name) + } + + // https://fetch.spec.whatwg.org/#concept-header-list-get + get (name) { + const value = this[kHeadersMap].get(name.toLowerCase()) + + // 1. If list does not contain name, then return null. + // 2. Return the values of all headers in list whose name + // is a byte-case-insensitive match for name, + // separated from each other by 0x2C 0x20, in order. + return value === undefined ? null : value.value + } + + * [Symbol.iterator] () { + // use the lowercased name + for (const [name, { value }] of this[kHeadersMap]) { + yield [name, value] + } + } + + get entries () { + const headers = {} + + if (this[kHeadersMap].size) { + for (const { name, value } of this[kHeadersMap].values()) { + headers[name] = value + } + } + + return headers + } +} + +// https://fetch.spec.whatwg.org/#headers-class +class Headers { + constructor (init = undefined) { + this[kHeadersList] = new HeadersList() + + // The new Headers(init) constructor steps are: + + // 1. Set this’s guard to "none". + this[kGuard] = 'none' + + // 2. If init is given, then fill this with init. + if (init !== undefined) { + init = webidl.converters.HeadersInit(init) + fill(this, init) + } + } + + // https://fetch.spec.whatwg.org/#dom-headers-append + append (name, value) { + webidl.brandCheck(this, Headers) + + webidl.argumentLengthCheck(arguments, 2, { header: 'Headers.append' }) + + name = webidl.converters.ByteString(name) + value = webidl.converters.ByteString(value) + + return appendHeader(this, name, value) + } + + // https://fetch.spec.whatwg.org/#dom-headers-delete + delete (name) { + webidl.brandCheck(this, Headers) + + webidl.argumentLengthCheck(arguments, 1, { header: 'Headers.delete' }) + + name = webidl.converters.ByteString(name) + + // 1. If name is not a header name, then throw a TypeError. + if (!isValidHeaderName(name)) { + throw webidl.errors.invalidArgument({ + prefix: 'Headers.delete', + value: name, + type: 'header name' + }) + } + + // 2. If this’s guard is "immutable", then throw a TypeError. + // 3. Otherwise, if this’s guard is "request" and name is a + // forbidden header name, return. + // 4. Otherwise, if this’s guard is "request-no-cors", name + // is not a no-CORS-safelisted request-header name, and + // name is not a privileged no-CORS request-header name, + // return. + // 5. Otherwise, if this’s guard is "response" and name is + // a forbidden response-header name, return. + // Note: undici does not implement forbidden header names + if (this[kGuard] === 'immutable') { + throw new TypeError('immutable') + } else if (this[kGuard] === 'request-no-cors') { + // TODO + } + + // 6. If this’s header list does not contain name, then + // return. + if (!this[kHeadersList].contains(name)) { + return + } + + // 7. Delete name from this’s header list. + // 8. If this’s guard is "request-no-cors", then remove + // privileged no-CORS request headers from this. + this[kHeadersList].delete(name) + } + + // https://fetch.spec.whatwg.org/#dom-headers-get + get (name) { + webidl.brandCheck(this, Headers) + + webidl.argumentLengthCheck(arguments, 1, { header: 'Headers.get' }) + + name = webidl.converters.ByteString(name) + + // 1. If name is not a header name, then throw a TypeError. + if (!isValidHeaderName(name)) { + throw webidl.errors.invalidArgument({ + prefix: 'Headers.get', + value: name, + type: 'header name' + }) + } + + // 2. Return the result of getting name from this’s header + // list. + return this[kHeadersList].get(name) + } + + // https://fetch.spec.whatwg.org/#dom-headers-has + has (name) { + webidl.brandCheck(this, Headers) + + webidl.argumentLengthCheck(arguments, 1, { header: 'Headers.has' }) + + name = webidl.converters.ByteString(name) + + // 1. If name is not a header name, then throw a TypeError. + if (!isValidHeaderName(name)) { + throw webidl.errors.invalidArgument({ + prefix: 'Headers.has', + value: name, + type: 'header name' + }) + } + + // 2. Return true if this’s header list contains name; + // otherwise false. + return this[kHeadersList].contains(name) + } + + // https://fetch.spec.whatwg.org/#dom-headers-set + set (name, value) { + webidl.brandCheck(this, Headers) + + webidl.argumentLengthCheck(arguments, 2, { header: 'Headers.set' }) + + name = webidl.converters.ByteString(name) + value = webidl.converters.ByteString(value) + + // 1. Normalize value. + value = headerValueNormalize(value) + + // 2. If name is not a header name or value is not a + // header value, then throw a TypeError. + if (!isValidHeaderName(name)) { + throw webidl.errors.invalidArgument({ + prefix: 'Headers.set', + value: name, + type: 'header name' + }) + } else if (!isValidHeaderValue(value)) { + throw webidl.errors.invalidArgument({ + prefix: 'Headers.set', + value, + type: 'header value' + }) + } + + // 3. If this’s guard is "immutable", then throw a TypeError. + // 4. Otherwise, if this’s guard is "request" and name is a + // forbidden header name, return. + // 5. Otherwise, if this’s guard is "request-no-cors" and + // name/value is not a no-CORS-safelisted request-header, + // return. + // 6. Otherwise, if this’s guard is "response" and name is a + // forbidden response-header name, return. + // Note: undici does not implement forbidden header names + if (this[kGuard] === 'immutable') { + throw new TypeError('immutable') + } else if (this[kGuard] === 'request-no-cors') { + // TODO + } + + // 7. Set (name, value) in this’s header list. + // 8. If this’s guard is "request-no-cors", then remove + // privileged no-CORS request headers from this + this[kHeadersList].set(name, value) + } + + // https://fetch.spec.whatwg.org/#dom-headers-getsetcookie + getSetCookie () { + webidl.brandCheck(this, Headers) + + // 1. If this’s header list does not contain `Set-Cookie`, then return « ». + // 2. Return the values of all headers in this’s header list whose name is + // a byte-case-insensitive match for `Set-Cookie`, in order. + + const list = this[kHeadersList].cookies + + if (list) { + return [...list] + } + + return [] + } + + // https://fetch.spec.whatwg.org/#concept-header-list-sort-and-combine + get [kHeadersSortedMap] () { + if (this[kHeadersList][kHeadersSortedMap]) { + return this[kHeadersList][kHeadersSortedMap] + } + + // 1. Let headers be an empty list of headers with the key being the name + // and value the value. + const headers = [] + + // 2. Let names be the result of convert header names to a sorted-lowercase + // set with all the names of the headers in list. + const names = [...this[kHeadersList]].sort((a, b) => a[0] < b[0] ? -1 : 1) + const cookies = this[kHeadersList].cookies + + // 3. For each name of names: + for (let i = 0; i < names.length; ++i) { + const [name, value] = names[i] + // 1. If name is `set-cookie`, then: + if (name === 'set-cookie') { + // 1. Let values be a list of all values of headers in list whose name + // is a byte-case-insensitive match for name, in order. + + // 2. For each value of values: + // 1. Append (name, value) to headers. + for (let j = 0; j < cookies.length; ++j) { + headers.push([name, cookies[j]]) + } + } else { + // 2. Otherwise: + + // 1. Let value be the result of getting name from list. + + // 2. Assert: value is non-null. + assert(value !== null) + + // 3. Append (name, value) to headers. + headers.push([name, value]) + } + } + + this[kHeadersList][kHeadersSortedMap] = headers + + // 4. Return headers. + return headers + } + + keys () { + webidl.brandCheck(this, Headers) + + if (this[kGuard] === 'immutable') { + const value = this[kHeadersSortedMap] + return makeIterator(() => value, 'Headers', + 'key') + } + + return makeIterator( + () => [...this[kHeadersSortedMap].values()], + 'Headers', + 'key' + ) + } + + values () { + webidl.brandCheck(this, Headers) + + if (this[kGuard] === 'immutable') { + const value = this[kHeadersSortedMap] + return makeIterator(() => value, 'Headers', + 'value') + } + + return makeIterator( + () => [...this[kHeadersSortedMap].values()], + 'Headers', + 'value' + ) + } + + entries () { + webidl.brandCheck(this, Headers) + + if (this[kGuard] === 'immutable') { + const value = this[kHeadersSortedMap] + return makeIterator(() => value, 'Headers', + 'key+value') + } + + return makeIterator( + () => [...this[kHeadersSortedMap].values()], + 'Headers', + 'key+value' + ) + } + + /** + * @param {(value: string, key: string, self: Headers) => void} callbackFn + * @param {unknown} thisArg + */ + forEach (callbackFn, thisArg = globalThis) { + webidl.brandCheck(this, Headers) + + webidl.argumentLengthCheck(arguments, 1, { header: 'Headers.forEach' }) + + if (typeof callbackFn !== 'function') { + throw new TypeError( + "Failed to execute 'forEach' on 'Headers': parameter 1 is not of type 'Function'." + ) + } + + for (const [key, value] of this) { + callbackFn.apply(thisArg, [value, key, this]) + } + } + + [Symbol.for('nodejs.util.inspect.custom')] () { + webidl.brandCheck(this, Headers) + + return this[kHeadersList] + } +} + +Headers.prototype[Symbol.iterator] = Headers.prototype.entries + +Object.defineProperties(Headers.prototype, { + append: kEnumerableProperty, + delete: kEnumerableProperty, + get: kEnumerableProperty, + has: kEnumerableProperty, + set: kEnumerableProperty, + getSetCookie: kEnumerableProperty, + keys: kEnumerableProperty, + values: kEnumerableProperty, + entries: kEnumerableProperty, + forEach: kEnumerableProperty, + [Symbol.iterator]: { enumerable: false }, + [Symbol.toStringTag]: { + value: 'Headers', + configurable: true + } +}) + +webidl.converters.HeadersInit = function (V) { + if (webidl.util.Type(V) === 'Object') { + if (V[Symbol.iterator]) { + return webidl.converters['sequence>'](V) + } + + return webidl.converters['record'](V) + } + + throw webidl.errors.conversionFailed({ + prefix: 'Headers constructor', + argument: 'Argument 1', + types: ['sequence>', 'record'] + }) +} + +module.exports = { + fill, + Headers, + HeadersList +} + + +/***/ }), + +/***/ 5935: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; +// https://github.com/Ethan-Arrowood/undici-fetch + + + +const { + Response, + makeNetworkError, + makeAppropriateNetworkError, + filterResponse, + makeResponse +} = __nccwpck_require__(5796) +const { Headers } = __nccwpck_require__(7689) +const { Request, makeRequest } = __nccwpck_require__(9157) +const zlib = __nccwpck_require__(9796) +const { + bytesMatch, + makePolicyContainer, + clonePolicyContainer, + requestBadPort, + TAOCheck, + appendRequestOriginHeader, + responseLocationURL, + requestCurrentURL, + setRequestReferrerPolicyOnRedirect, + tryUpgradeRequestToAPotentiallyTrustworthyURL, + createOpaqueTimingInfo, + appendFetchMetadata, + corsCheck, + crossOriginResourcePolicyCheck, + determineRequestsReferrer, + coarsenedSharedCurrentTime, + createDeferredPromise, + isBlobLike, + sameOrigin, + isCancelled, + isAborted, + isErrorLike, + fullyReadBody, + readableStreamClose, + isomorphicEncode, + urlIsLocal, + urlIsHttpHttpsScheme, + urlHasHttpsScheme +} = __nccwpck_require__(784) +const { kState, kHeaders, kGuard, kRealm } = __nccwpck_require__(8085) +const assert = __nccwpck_require__(9491) +const { safelyExtractBody } = __nccwpck_require__(804) +const { + redirectStatusSet, + nullBodyStatus, + safeMethodsSet, + requestBodyHeader, + subresourceSet, + DOMException +} = __nccwpck_require__(7059) +const { kHeadersList } = __nccwpck_require__(9440) +const EE = __nccwpck_require__(2361) +const { Readable, pipeline } = __nccwpck_require__(2781) +const { addAbortListener, isErrored, isReadable, nodeMajor, nodeMinor } = __nccwpck_require__(9522) +const { dataURLProcessor, serializeAMimeType } = __nccwpck_require__(2791) +const { TransformStream } = __nccwpck_require__(5356) +const { getGlobalDispatcher } = __nccwpck_require__(5035) +const { webidl } = __nccwpck_require__(1537) +const { STATUS_CODES } = __nccwpck_require__(3685) +const GET_OR_HEAD = ['GET', 'HEAD'] + +/** @type {import('buffer').resolveObjectURL} */ +let resolveObjectURL +let ReadableStream = globalThis.ReadableStream + +class Fetch extends EE { + constructor (dispatcher) { + super() + + this.dispatcher = dispatcher + this.connection = null + this.dump = false + this.state = 'ongoing' + // 2 terminated listeners get added per request, + // but only 1 gets removed. If there are 20 redirects, + // 21 listeners will be added. + // See https://github.com/nodejs/undici/issues/1711 + // TODO (fix): Find and fix root cause for leaked listener. + this.setMaxListeners(21) + } + + terminate (reason) { + if (this.state !== 'ongoing') { + return + } + + this.state = 'terminated' + this.connection?.destroy(reason) + this.emit('terminated', reason) + } + + // https://fetch.spec.whatwg.org/#fetch-controller-abort + abort (error) { + if (this.state !== 'ongoing') { + return + } + + // 1. Set controller’s state to "aborted". + this.state = 'aborted' + + // 2. Let fallbackError be an "AbortError" DOMException. + // 3. Set error to fallbackError if it is not given. + if (!error) { + error = new DOMException('The operation was aborted.', 'AbortError') + } + + // 4. Let serializedError be StructuredSerialize(error). + // If that threw an exception, catch it, and let + // serializedError be StructuredSerialize(fallbackError). + + // 5. Set controller’s serialized abort reason to serializedError. + this.serializedAbortReason = error + + this.connection?.destroy(error) + this.emit('terminated', error) + } +} + +// https://fetch.spec.whatwg.org/#fetch-method +function fetch (input, init = {}) { + webidl.argumentLengthCheck(arguments, 1, { header: 'globalThis.fetch' }) + + // 1. Let p be a new promise. + const p = createDeferredPromise() + + // 2. Let requestObject be the result of invoking the initial value of + // Request as constructor with input and init as arguments. If this throws + // an exception, reject p with it and return p. + let requestObject + + try { + requestObject = new Request(input, init) + } catch (e) { + p.reject(e) + return p.promise + } + + // 3. Let request be requestObject’s request. + const request = requestObject[kState] + + // 4. If requestObject’s signal’s aborted flag is set, then: + if (requestObject.signal.aborted) { + // 1. Abort the fetch() call with p, request, null, and + // requestObject’s signal’s abort reason. + abortFetch(p, request, null, requestObject.signal.reason) + + // 2. Return p. + return p.promise + } + + // 5. Let globalObject be request’s client’s global object. + const globalObject = request.client.globalObject + + // 6. If globalObject is a ServiceWorkerGlobalScope object, then set + // request’s service-workers mode to "none". + if (globalObject?.constructor?.name === 'ServiceWorkerGlobalScope') { + request.serviceWorkers = 'none' + } + + // 7. Let responseObject be null. + let responseObject = null + + // 8. Let relevantRealm be this’s relevant Realm. + const relevantRealm = null + + // 9. Let locallyAborted be false. + let locallyAborted = false + + // 10. Let controller be null. + let controller = null + + // 11. Add the following abort steps to requestObject’s signal: + addAbortListener( + requestObject.signal, + () => { + // 1. Set locallyAborted to true. + locallyAborted = true + + // 2. Assert: controller is non-null. + assert(controller != null) + + // 3. Abort controller with requestObject’s signal’s abort reason. + controller.abort(requestObject.signal.reason) + + // 4. Abort the fetch() call with p, request, responseObject, + // and requestObject’s signal’s abort reason. + abortFetch(p, request, responseObject, requestObject.signal.reason) + } + ) + + // 12. Let handleFetchDone given response response be to finalize and + // report timing with response, globalObject, and "fetch". + const handleFetchDone = (response) => + finalizeAndReportTiming(response, 'fetch') + + // 13. Set controller to the result of calling fetch given request, + // with processResponseEndOfBody set to handleFetchDone, and processResponse + // given response being these substeps: + + const processResponse = (response) => { + // 1. If locallyAborted is true, terminate these substeps. + if (locallyAborted) { + return Promise.resolve() + } + + // 2. If response’s aborted flag is set, then: + if (response.aborted) { + // 1. Let deserializedError be the result of deserialize a serialized + // abort reason given controller’s serialized abort reason and + // relevantRealm. + + // 2. Abort the fetch() call with p, request, responseObject, and + // deserializedError. + + abortFetch(p, request, responseObject, controller.serializedAbortReason) + return Promise.resolve() + } + + // 3. If response is a network error, then reject p with a TypeError + // and terminate these substeps. + if (response.type === 'error') { + p.reject( + Object.assign(new TypeError('fetch failed'), { cause: response.error }) + ) + return Promise.resolve() + } + + // 4. Set responseObject to the result of creating a Response object, + // given response, "immutable", and relevantRealm. + responseObject = new Response() + responseObject[kState] = response + responseObject[kRealm] = relevantRealm + responseObject[kHeaders][kHeadersList] = response.headersList + responseObject[kHeaders][kGuard] = 'immutable' + responseObject[kHeaders][kRealm] = relevantRealm + + // 5. Resolve p with responseObject. + p.resolve(responseObject) + } + + controller = fetching({ + request, + processResponseEndOfBody: handleFetchDone, + processResponse, + dispatcher: init.dispatcher ?? getGlobalDispatcher() // undici + }) + + // 14. Return p. + return p.promise +} + +// https://fetch.spec.whatwg.org/#finalize-and-report-timing +function finalizeAndReportTiming (response, initiatorType = 'other') { + // 1. If response is an aborted network error, then return. + if (response.type === 'error' && response.aborted) { + return + } + + // 2. If response’s URL list is null or empty, then return. + if (!response.urlList?.length) { + return + } + + // 3. Let originalURL be response’s URL list[0]. + const originalURL = response.urlList[0] + + // 4. Let timingInfo be response’s timing info. + let timingInfo = response.timingInfo + + // 5. Let cacheState be response’s cache state. + let cacheState = response.cacheState + + // 6. If originalURL’s scheme is not an HTTP(S) scheme, then return. + if (!urlIsHttpHttpsScheme(originalURL)) { + return + } + + // 7. If timingInfo is null, then return. + if (timingInfo === null) { + return + } + + // 8. If response’s timing allow passed flag is not set, then: + if (!timingInfo.timingAllowPassed) { + // 1. Set timingInfo to a the result of creating an opaque timing info for timingInfo. + timingInfo = createOpaqueTimingInfo({ + startTime: timingInfo.startTime + }) + + // 2. Set cacheState to the empty string. + cacheState = '' + } + + // 9. Set timingInfo’s end time to the coarsened shared current time + // given global’s relevant settings object’s cross-origin isolated + // capability. + // TODO: given global’s relevant settings object’s cross-origin isolated + // capability? + timingInfo.endTime = coarsenedSharedCurrentTime() + + // 10. Set response’s timing info to timingInfo. + response.timingInfo = timingInfo + + // 11. Mark resource timing for timingInfo, originalURL, initiatorType, + // global, and cacheState. + markResourceTiming( + timingInfo, + originalURL, + initiatorType, + globalThis, + cacheState + ) +} + +// https://w3c.github.io/resource-timing/#dfn-mark-resource-timing +function markResourceTiming (timingInfo, originalURL, initiatorType, globalThis, cacheState) { + if (nodeMajor > 18 || (nodeMajor === 18 && nodeMinor >= 2)) { + performance.markResourceTiming(timingInfo, originalURL.href, initiatorType, globalThis, cacheState) + } +} + +// https://fetch.spec.whatwg.org/#abort-fetch +function abortFetch (p, request, responseObject, error) { + // Note: AbortSignal.reason was added in node v17.2.0 + // which would give us an undefined error to reject with. + // Remove this once node v16 is no longer supported. + if (!error) { + error = new DOMException('The operation was aborted.', 'AbortError') + } + + // 1. Reject promise with error. + p.reject(error) + + // 2. If request’s body is not null and is readable, then cancel request’s + // body with error. + if (request.body != null && isReadable(request.body?.stream)) { + request.body.stream.cancel(error).catch((err) => { + if (err.code === 'ERR_INVALID_STATE') { + // Node bug? + return + } + throw err + }) + } + + // 3. If responseObject is null, then return. + if (responseObject == null) { + return + } + + // 4. Let response be responseObject’s response. + const response = responseObject[kState] + + // 5. If response’s body is not null and is readable, then error response’s + // body with error. + if (response.body != null && isReadable(response.body?.stream)) { + response.body.stream.cancel(error).catch((err) => { + if (err.code === 'ERR_INVALID_STATE') { + // Node bug? + return + } + throw err + }) + } +} + +// https://fetch.spec.whatwg.org/#fetching +function fetching ({ + request, + processRequestBodyChunkLength, + processRequestEndOfBody, + processResponse, + processResponseEndOfBody, + processResponseConsumeBody, + useParallelQueue = false, + dispatcher // undici +}) { + // 1. Let taskDestination be null. + let taskDestination = null + + // 2. Let crossOriginIsolatedCapability be false. + let crossOriginIsolatedCapability = false + + // 3. If request’s client is non-null, then: + if (request.client != null) { + // 1. Set taskDestination to request’s client’s global object. + taskDestination = request.client.globalObject + + // 2. Set crossOriginIsolatedCapability to request’s client’s cross-origin + // isolated capability. + crossOriginIsolatedCapability = + request.client.crossOriginIsolatedCapability + } + + // 4. If useParallelQueue is true, then set taskDestination to the result of + // starting a new parallel queue. + // TODO + + // 5. Let timingInfo be a new fetch timing info whose start time and + // post-redirect start time are the coarsened shared current time given + // crossOriginIsolatedCapability. + const currenTime = coarsenedSharedCurrentTime(crossOriginIsolatedCapability) + const timingInfo = createOpaqueTimingInfo({ + startTime: currenTime + }) + + // 6. Let fetchParams be a new fetch params whose + // request is request, + // timing info is timingInfo, + // process request body chunk length is processRequestBodyChunkLength, + // process request end-of-body is processRequestEndOfBody, + // process response is processResponse, + // process response consume body is processResponseConsumeBody, + // process response end-of-body is processResponseEndOfBody, + // task destination is taskDestination, + // and cross-origin isolated capability is crossOriginIsolatedCapability. + const fetchParams = { + controller: new Fetch(dispatcher), + request, + timingInfo, + processRequestBodyChunkLength, + processRequestEndOfBody, + processResponse, + processResponseConsumeBody, + processResponseEndOfBody, + taskDestination, + crossOriginIsolatedCapability + } + + // 7. If request’s body is a byte sequence, then set request’s body to + // request’s body as a body. + // NOTE: Since fetching is only called from fetch, body should already be + // extracted. + assert(!request.body || request.body.stream) + + // 8. If request’s window is "client", then set request’s window to request’s + // client, if request’s client’s global object is a Window object; otherwise + // "no-window". + if (request.window === 'client') { + // TODO: What if request.client is null? + request.window = + request.client?.globalObject?.constructor?.name === 'Window' + ? request.client + : 'no-window' + } + + // 9. If request’s origin is "client", then set request’s origin to request’s + // client’s origin. + if (request.origin === 'client') { + // TODO: What if request.client is null? + request.origin = request.client?.origin + } + + // 10. If all of the following conditions are true: + // TODO + + // 11. If request’s policy container is "client", then: + if (request.policyContainer === 'client') { + // 1. If request’s client is non-null, then set request’s policy + // container to a clone of request’s client’s policy container. [HTML] + if (request.client != null) { + request.policyContainer = clonePolicyContainer( + request.client.policyContainer + ) + } else { + // 2. Otherwise, set request’s policy container to a new policy + // container. + request.policyContainer = makePolicyContainer() + } + } + + // 12. If request’s header list does not contain `Accept`, then: + if (!request.headersList.contains('accept')) { + // 1. Let value be `*/*`. + const value = '*/*' + + // 2. A user agent should set value to the first matching statement, if + // any, switching on request’s destination: + // "document" + // "frame" + // "iframe" + // `text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8` + // "image" + // `image/png,image/svg+xml,image/*;q=0.8,*/*;q=0.5` + // "style" + // `text/css,*/*;q=0.1` + // TODO + + // 3. Append `Accept`/value to request’s header list. + request.headersList.append('accept', value) + } + + // 13. If request’s header list does not contain `Accept-Language`, then + // user agents should append `Accept-Language`/an appropriate value to + // request’s header list. + if (!request.headersList.contains('accept-language')) { + request.headersList.append('accept-language', '*') + } + + // 14. If request’s priority is null, then use request’s initiator and + // destination appropriately in setting request’s priority to a + // user-agent-defined object. + if (request.priority === null) { + // TODO + } + + // 15. If request is a subresource request, then: + if (subresourceSet.has(request.destination)) { + // TODO + } + + // 16. Run main fetch given fetchParams. + mainFetch(fetchParams) + .catch(err => { + fetchParams.controller.terminate(err) + }) + + // 17. Return fetchParam's controller + return fetchParams.controller +} + +// https://fetch.spec.whatwg.org/#concept-main-fetch +async function mainFetch (fetchParams, recursive = false) { + // 1. Let request be fetchParams’s request. + const request = fetchParams.request + + // 2. Let response be null. + let response = null + + // 3. If request’s local-URLs-only flag is set and request’s current URL is + // not local, then set response to a network error. + if (request.localURLsOnly && !urlIsLocal(requestCurrentURL(request))) { + response = makeNetworkError('local URLs only') + } + + // 4. Run report Content Security Policy violations for request. + // TODO + + // 5. Upgrade request to a potentially trustworthy URL, if appropriate. + tryUpgradeRequestToAPotentiallyTrustworthyURL(request) + + // 6. If should request be blocked due to a bad port, should fetching request + // be blocked as mixed content, or should request be blocked by Content + // Security Policy returns blocked, then set response to a network error. + if (requestBadPort(request) === 'blocked') { + response = makeNetworkError('bad port') + } + // TODO: should fetching request be blocked as mixed content? + // TODO: should request be blocked by Content Security Policy? + + // 7. If request’s referrer policy is the empty string, then set request’s + // referrer policy to request’s policy container’s referrer policy. + if (request.referrerPolicy === '') { + request.referrerPolicy = request.policyContainer.referrerPolicy + } + + // 8. If request’s referrer is not "no-referrer", then set request’s + // referrer to the result of invoking determine request’s referrer. + if (request.referrer !== 'no-referrer') { + request.referrer = determineRequestsReferrer(request) + } + + // 9. Set request’s current URL’s scheme to "https" if all of the following + // conditions are true: + // - request’s current URL’s scheme is "http" + // - request’s current URL’s host is a domain + // - Matching request’s current URL’s host per Known HSTS Host Domain Name + // Matching results in either a superdomain match with an asserted + // includeSubDomains directive or a congruent match (with or without an + // asserted includeSubDomains directive). [HSTS] + // TODO + + // 10. If recursive is false, then run the remaining steps in parallel. + // TODO + + // 11. If response is null, then set response to the result of running + // the steps corresponding to the first matching statement: + if (response === null) { + response = await (async () => { + const currentURL = requestCurrentURL(request) + + if ( + // - request’s current URL’s origin is same origin with request’s origin, + // and request’s response tainting is "basic" + (sameOrigin(currentURL, request.url) && request.responseTainting === 'basic') || + // request’s current URL’s scheme is "data" + (currentURL.protocol === 'data:') || + // - request’s mode is "navigate" or "websocket" + (request.mode === 'navigate' || request.mode === 'websocket') + ) { + // 1. Set request’s response tainting to "basic". + request.responseTainting = 'basic' + + // 2. Return the result of running scheme fetch given fetchParams. + return await schemeFetch(fetchParams) + } + + // request’s mode is "same-origin" + if (request.mode === 'same-origin') { + // 1. Return a network error. + return makeNetworkError('request mode cannot be "same-origin"') + } + + // request’s mode is "no-cors" + if (request.mode === 'no-cors') { + // 1. If request’s redirect mode is not "follow", then return a network + // error. + if (request.redirect !== 'follow') { + return makeNetworkError( + 'redirect mode cannot be "follow" for "no-cors" request' + ) + } + + // 2. Set request’s response tainting to "opaque". + request.responseTainting = 'opaque' + + // 3. Return the result of running scheme fetch given fetchParams. + return await schemeFetch(fetchParams) + } + + // request’s current URL’s scheme is not an HTTP(S) scheme + if (!urlIsHttpHttpsScheme(requestCurrentURL(request))) { + // Return a network error. + return makeNetworkError('URL scheme must be a HTTP(S) scheme') + } + + // - request’s use-CORS-preflight flag is set + // - request’s unsafe-request flag is set and either request’s method is + // not a CORS-safelisted method or CORS-unsafe request-header names with + // request’s header list is not empty + // 1. Set request’s response tainting to "cors". + // 2. Let corsWithPreflightResponse be the result of running HTTP fetch + // given fetchParams and true. + // 3. If corsWithPreflightResponse is a network error, then clear cache + // entries using request. + // 4. Return corsWithPreflightResponse. + // TODO + + // Otherwise + // 1. Set request’s response tainting to "cors". + request.responseTainting = 'cors' + + // 2. Return the result of running HTTP fetch given fetchParams. + return await httpFetch(fetchParams) + })() + } + + // 12. If recursive is true, then return response. + if (recursive) { + return response + } + + // 13. If response is not a network error and response is not a filtered + // response, then: + if (response.status !== 0 && !response.internalResponse) { + // If request’s response tainting is "cors", then: + if (request.responseTainting === 'cors') { + // 1. Let headerNames be the result of extracting header list values + // given `Access-Control-Expose-Headers` and response’s header list. + // TODO + // 2. If request’s credentials mode is not "include" and headerNames + // contains `*`, then set response’s CORS-exposed header-name list to + // all unique header names in response’s header list. + // TODO + // 3. Otherwise, if headerNames is not null or failure, then set + // response’s CORS-exposed header-name list to headerNames. + // TODO + } + + // Set response to the following filtered response with response as its + // internal response, depending on request’s response tainting: + if (request.responseTainting === 'basic') { + response = filterResponse(response, 'basic') + } else if (request.responseTainting === 'cors') { + response = filterResponse(response, 'cors') + } else if (request.responseTainting === 'opaque') { + response = filterResponse(response, 'opaque') + } else { + assert(false) + } + } + + // 14. Let internalResponse be response, if response is a network error, + // and response’s internal response otherwise. + let internalResponse = + response.status === 0 ? response : response.internalResponse + + // 15. If internalResponse’s URL list is empty, then set it to a clone of + // request’s URL list. + if (internalResponse.urlList.length === 0) { + internalResponse.urlList.push(...request.urlList) + } + + // 16. If request’s timing allow failed flag is unset, then set + // internalResponse’s timing allow passed flag. + if (!request.timingAllowFailed) { + response.timingAllowPassed = true + } + + // 17. If response is not a network error and any of the following returns + // blocked + // - should internalResponse to request be blocked as mixed content + // - should internalResponse to request be blocked by Content Security Policy + // - should internalResponse to request be blocked due to its MIME type + // - should internalResponse to request be blocked due to nosniff + // TODO + + // 18. If response’s type is "opaque", internalResponse’s status is 206, + // internalResponse’s range-requested flag is set, and request’s header + // list does not contain `Range`, then set response and internalResponse + // to a network error. + if ( + response.type === 'opaque' && + internalResponse.status === 206 && + internalResponse.rangeRequested && + !request.headers.contains('range') + ) { + response = internalResponse = makeNetworkError() + } + + // 19. If response is not a network error and either request’s method is + // `HEAD` or `CONNECT`, or internalResponse’s status is a null body status, + // set internalResponse’s body to null and disregard any enqueuing toward + // it (if any). + if ( + response.status !== 0 && + (request.method === 'HEAD' || + request.method === 'CONNECT' || + nullBodyStatus.includes(internalResponse.status)) + ) { + internalResponse.body = null + fetchParams.controller.dump = true + } + + // 20. If request’s integrity metadata is not the empty string, then: + if (request.integrity) { + // 1. Let processBodyError be this step: run fetch finale given fetchParams + // and a network error. + const processBodyError = (reason) => + fetchFinale(fetchParams, makeNetworkError(reason)) + + // 2. If request’s response tainting is "opaque", or response’s body is null, + // then run processBodyError and abort these steps. + if (request.responseTainting === 'opaque' || response.body == null) { + processBodyError(response.error) + return + } + + // 3. Let processBody given bytes be these steps: + const processBody = (bytes) => { + // 1. If bytes do not match request’s integrity metadata, + // then run processBodyError and abort these steps. [SRI] + if (!bytesMatch(bytes, request.integrity)) { + processBodyError('integrity mismatch') + return + } + + // 2. Set response’s body to bytes as a body. + response.body = safelyExtractBody(bytes)[0] + + // 3. Run fetch finale given fetchParams and response. + fetchFinale(fetchParams, response) + } + + // 4. Fully read response’s body given processBody and processBodyError. + await fullyReadBody(response.body, processBody, processBodyError) + } else { + // 21. Otherwise, run fetch finale given fetchParams and response. + fetchFinale(fetchParams, response) + } +} + +// https://fetch.spec.whatwg.org/#concept-scheme-fetch +// given a fetch params fetchParams +function schemeFetch (fetchParams) { + // Note: since the connection is destroyed on redirect, which sets fetchParams to a + // cancelled state, we do not want this condition to trigger *unless* there have been + // no redirects. See https://github.com/nodejs/undici/issues/1776 + // 1. If fetchParams is canceled, then return the appropriate network error for fetchParams. + if (isCancelled(fetchParams) && fetchParams.request.redirectCount === 0) { + return Promise.resolve(makeAppropriateNetworkError(fetchParams)) + } + + // 2. Let request be fetchParams’s request. + const { request } = fetchParams + + const { protocol: scheme } = requestCurrentURL(request) + + // 3. Switch on request’s current URL’s scheme and run the associated steps: + switch (scheme) { + case 'about:': { + // If request’s current URL’s path is the string "blank", then return a new response + // whose status message is `OK`, header list is « (`Content-Type`, `text/html;charset=utf-8`) », + // and body is the empty byte sequence as a body. + + // Otherwise, return a network error. + return Promise.resolve(makeNetworkError('about scheme is not supported')) + } + case 'blob:': { + if (!resolveObjectURL) { + resolveObjectURL = (__nccwpck_require__(4300).resolveObjectURL) + } + + // 1. Let blobURLEntry be request’s current URL’s blob URL entry. + const blobURLEntry = requestCurrentURL(request) + + // https://github.com/web-platform-tests/wpt/blob/7b0ebaccc62b566a1965396e5be7bb2bc06f841f/FileAPI/url/resources/fetch-tests.js#L52-L56 + // Buffer.resolveObjectURL does not ignore URL queries. + if (blobURLEntry.search.length !== 0) { + return Promise.resolve(makeNetworkError('NetworkError when attempting to fetch resource.')) + } + + const blobURLEntryObject = resolveObjectURL(blobURLEntry.toString()) + + // 2. If request’s method is not `GET`, blobURLEntry is null, or blobURLEntry’s + // object is not a Blob object, then return a network error. + if (request.method !== 'GET' || !isBlobLike(blobURLEntryObject)) { + return Promise.resolve(makeNetworkError('invalid method')) + } + + // 3. Let bodyWithType be the result of safely extracting blobURLEntry’s object. + const bodyWithType = safelyExtractBody(blobURLEntryObject) + + // 4. Let body be bodyWithType’s body. + const body = bodyWithType[0] + + // 5. Let length be body’s length, serialized and isomorphic encoded. + const length = isomorphicEncode(`${body.length}`) + + // 6. Let type be bodyWithType’s type if it is non-null; otherwise the empty byte sequence. + const type = bodyWithType[1] ?? '' + + // 7. Return a new response whose status message is `OK`, header list is + // « (`Content-Length`, length), (`Content-Type`, type) », and body is body. + const response = makeResponse({ + statusText: 'OK', + headersList: [ + ['content-length', { name: 'Content-Length', value: length }], + ['content-type', { name: 'Content-Type', value: type }] + ] + }) + + response.body = body + + return Promise.resolve(response) + } + case 'data:': { + // 1. Let dataURLStruct be the result of running the + // data: URL processor on request’s current URL. + const currentURL = requestCurrentURL(request) + const dataURLStruct = dataURLProcessor(currentURL) + + // 2. If dataURLStruct is failure, then return a + // network error. + if (dataURLStruct === 'failure') { + return Promise.resolve(makeNetworkError('failed to fetch the data URL')) + } + + // 3. Let mimeType be dataURLStruct’s MIME type, serialized. + const mimeType = serializeAMimeType(dataURLStruct.mimeType) + + // 4. Return a response whose status message is `OK`, + // header list is « (`Content-Type`, mimeType) », + // and body is dataURLStruct’s body as a body. + return Promise.resolve(makeResponse({ + statusText: 'OK', + headersList: [ + ['content-type', { name: 'Content-Type', value: mimeType }] + ], + body: safelyExtractBody(dataURLStruct.body)[0] + })) + } + case 'file:': { + // For now, unfortunate as it is, file URLs are left as an exercise for the reader. + // When in doubt, return a network error. + return Promise.resolve(makeNetworkError('not implemented... yet...')) + } + case 'http:': + case 'https:': { + // Return the result of running HTTP fetch given fetchParams. + + return httpFetch(fetchParams) + .catch((err) => makeNetworkError(err)) + } + default: { + return Promise.resolve(makeNetworkError('unknown scheme')) + } + } +} + +// https://fetch.spec.whatwg.org/#finalize-response +function finalizeResponse (fetchParams, response) { + // 1. Set fetchParams’s request’s done flag. + fetchParams.request.done = true + + // 2, If fetchParams’s process response done is not null, then queue a fetch + // task to run fetchParams’s process response done given response, with + // fetchParams’s task destination. + if (fetchParams.processResponseDone != null) { + queueMicrotask(() => fetchParams.processResponseDone(response)) + } +} + +// https://fetch.spec.whatwg.org/#fetch-finale +function fetchFinale (fetchParams, response) { + // 1. If response is a network error, then: + if (response.type === 'error') { + // 1. Set response’s URL list to « fetchParams’s request’s URL list[0] ». + response.urlList = [fetchParams.request.urlList[0]] + + // 2. Set response’s timing info to the result of creating an opaque timing + // info for fetchParams’s timing info. + response.timingInfo = createOpaqueTimingInfo({ + startTime: fetchParams.timingInfo.startTime + }) + } + + // 2. Let processResponseEndOfBody be the following steps: + const processResponseEndOfBody = () => { + // 1. Set fetchParams’s request’s done flag. + fetchParams.request.done = true + + // If fetchParams’s process response end-of-body is not null, + // then queue a fetch task to run fetchParams’s process response + // end-of-body given response with fetchParams’s task destination. + if (fetchParams.processResponseEndOfBody != null) { + queueMicrotask(() => fetchParams.processResponseEndOfBody(response)) + } + } + + // 3. If fetchParams’s process response is non-null, then queue a fetch task + // to run fetchParams’s process response given response, with fetchParams’s + // task destination. + if (fetchParams.processResponse != null) { + queueMicrotask(() => fetchParams.processResponse(response)) + } + + // 4. If response’s body is null, then run processResponseEndOfBody. + if (response.body == null) { + processResponseEndOfBody() + } else { + // 5. Otherwise: + + // 1. Let transformStream be a new a TransformStream. + + // 2. Let identityTransformAlgorithm be an algorithm which, given chunk, + // enqueues chunk in transformStream. + const identityTransformAlgorithm = (chunk, controller) => { + controller.enqueue(chunk) + } + + // 3. Set up transformStream with transformAlgorithm set to identityTransformAlgorithm + // and flushAlgorithm set to processResponseEndOfBody. + const transformStream = new TransformStream({ + start () {}, + transform: identityTransformAlgorithm, + flush: processResponseEndOfBody + }, { + size () { + return 1 + } + }, { + size () { + return 1 + } + }) + + // 4. Set response’s body to the result of piping response’s body through transformStream. + response.body = { stream: response.body.stream.pipeThrough(transformStream) } + } + + // 6. If fetchParams’s process response consume body is non-null, then: + if (fetchParams.processResponseConsumeBody != null) { + // 1. Let processBody given nullOrBytes be this step: run fetchParams’s + // process response consume body given response and nullOrBytes. + const processBody = (nullOrBytes) => fetchParams.processResponseConsumeBody(response, nullOrBytes) + + // 2. Let processBodyError be this step: run fetchParams’s process + // response consume body given response and failure. + const processBodyError = (failure) => fetchParams.processResponseConsumeBody(response, failure) + + // 3. If response’s body is null, then queue a fetch task to run processBody + // given null, with fetchParams’s task destination. + if (response.body == null) { + queueMicrotask(() => processBody(null)) + } else { + // 4. Otherwise, fully read response’s body given processBody, processBodyError, + // and fetchParams’s task destination. + return fullyReadBody(response.body, processBody, processBodyError) + } + return Promise.resolve() + } +} + +// https://fetch.spec.whatwg.org/#http-fetch +async function httpFetch (fetchParams) { + // 1. Let request be fetchParams’s request. + const request = fetchParams.request + + // 2. Let response be null. + let response = null + + // 3. Let actualResponse be null. + let actualResponse = null + + // 4. Let timingInfo be fetchParams’s timing info. + const timingInfo = fetchParams.timingInfo + + // 5. If request’s service-workers mode is "all", then: + if (request.serviceWorkers === 'all') { + // TODO + } + + // 6. If response is null, then: + if (response === null) { + // 1. If makeCORSPreflight is true and one of these conditions is true: + // TODO + + // 2. If request’s redirect mode is "follow", then set request’s + // service-workers mode to "none". + if (request.redirect === 'follow') { + request.serviceWorkers = 'none' + } + + // 3. Set response and actualResponse to the result of running + // HTTP-network-or-cache fetch given fetchParams. + actualResponse = response = await httpNetworkOrCacheFetch(fetchParams) + + // 4. If request’s response tainting is "cors" and a CORS check + // for request and response returns failure, then return a network error. + if ( + request.responseTainting === 'cors' && + corsCheck(request, response) === 'failure' + ) { + return makeNetworkError('cors failure') + } + + // 5. If the TAO check for request and response returns failure, then set + // request’s timing allow failed flag. + if (TAOCheck(request, response) === 'failure') { + request.timingAllowFailed = true + } + } + + // 7. If either request’s response tainting or response’s type + // is "opaque", and the cross-origin resource policy check with + // request’s origin, request’s client, request’s destination, + // and actualResponse returns blocked, then return a network error. + if ( + (request.responseTainting === 'opaque' || response.type === 'opaque') && + crossOriginResourcePolicyCheck( + request.origin, + request.client, + request.destination, + actualResponse + ) === 'blocked' + ) { + return makeNetworkError('blocked') + } + + // 8. If actualResponse’s status is a redirect status, then: + if (redirectStatusSet.has(actualResponse.status)) { + // 1. If actualResponse’s status is not 303, request’s body is not null, + // and the connection uses HTTP/2, then user agents may, and are even + // encouraged to, transmit an RST_STREAM frame. + // See, https://github.com/whatwg/fetch/issues/1288 + if (request.redirect !== 'manual') { + fetchParams.controller.connection.destroy() + } + + // 2. Switch on request’s redirect mode: + if (request.redirect === 'error') { + // Set response to a network error. + response = makeNetworkError('unexpected redirect') + } else if (request.redirect === 'manual') { + // Set response to an opaque-redirect filtered response whose internal + // response is actualResponse. + // NOTE(spec): On the web this would return an `opaqueredirect` response, + // but that doesn't make sense server side. + // See https://github.com/nodejs/undici/issues/1193. + response = actualResponse + } else if (request.redirect === 'follow') { + // Set response to the result of running HTTP-redirect fetch given + // fetchParams and response. + response = await httpRedirectFetch(fetchParams, response) + } else { + assert(false) + } + } + + // 9. Set response’s timing info to timingInfo. + response.timingInfo = timingInfo + + // 10. Return response. + return response +} + +// https://fetch.spec.whatwg.org/#http-redirect-fetch +function httpRedirectFetch (fetchParams, response) { + // 1. Let request be fetchParams’s request. + const request = fetchParams.request + + // 2. Let actualResponse be response, if response is not a filtered response, + // and response’s internal response otherwise. + const actualResponse = response.internalResponse + ? response.internalResponse + : response + + // 3. Let locationURL be actualResponse’s location URL given request’s current + // URL’s fragment. + let locationURL + + try { + locationURL = responseLocationURL( + actualResponse, + requestCurrentURL(request).hash + ) + + // 4. If locationURL is null, then return response. + if (locationURL == null) { + return response + } + } catch (err) { + // 5. If locationURL is failure, then return a network error. + return Promise.resolve(makeNetworkError(err)) + } + + // 6. If locationURL’s scheme is not an HTTP(S) scheme, then return a network + // error. + if (!urlIsHttpHttpsScheme(locationURL)) { + return Promise.resolve(makeNetworkError('URL scheme must be a HTTP(S) scheme')) + } + + // 7. If request’s redirect count is 20, then return a network error. + if (request.redirectCount === 20) { + return Promise.resolve(makeNetworkError('redirect count exceeded')) + } + + // 8. Increase request’s redirect count by 1. + request.redirectCount += 1 + + // 9. If request’s mode is "cors", locationURL includes credentials, and + // request’s origin is not same origin with locationURL’s origin, then return + // a network error. + if ( + request.mode === 'cors' && + (locationURL.username || locationURL.password) && + !sameOrigin(request, locationURL) + ) { + return Promise.resolve(makeNetworkError('cross origin not allowed for request mode "cors"')) + } + + // 10. If request’s response tainting is "cors" and locationURL includes + // credentials, then return a network error. + if ( + request.responseTainting === 'cors' && + (locationURL.username || locationURL.password) + ) { + return Promise.resolve(makeNetworkError( + 'URL cannot contain credentials for request mode "cors"' + )) + } + + // 11. If actualResponse’s status is not 303, request’s body is non-null, + // and request’s body’s source is null, then return a network error. + if ( + actualResponse.status !== 303 && + request.body != null && + request.body.source == null + ) { + return Promise.resolve(makeNetworkError()) + } + + // 12. If one of the following is true + // - actualResponse’s status is 301 or 302 and request’s method is `POST` + // - actualResponse’s status is 303 and request’s method is not `GET` or `HEAD` + if ( + ([301, 302].includes(actualResponse.status) && request.method === 'POST') || + (actualResponse.status === 303 && + !GET_OR_HEAD.includes(request.method)) + ) { + // then: + // 1. Set request’s method to `GET` and request’s body to null. + request.method = 'GET' + request.body = null + + // 2. For each headerName of request-body-header name, delete headerName from + // request’s header list. + for (const headerName of requestBodyHeader) { + request.headersList.delete(headerName) + } + } + + // 13. If request’s current URL’s origin is not same origin with locationURL’s + // origin, then for each headerName of CORS non-wildcard request-header name, + // delete headerName from request’s header list. + if (!sameOrigin(requestCurrentURL(request), locationURL)) { + // https://fetch.spec.whatwg.org/#cors-non-wildcard-request-header-name + request.headersList.delete('authorization') + + // "Cookie" and "Host" are forbidden request-headers, which undici doesn't implement. + request.headersList.delete('cookie') + request.headersList.delete('host') + } + + // 14. If request’s body is non-null, then set request’s body to the first return + // value of safely extracting request’s body’s source. + if (request.body != null) { + assert(request.body.source != null) + request.body = safelyExtractBody(request.body.source)[0] + } + + // 15. Let timingInfo be fetchParams’s timing info. + const timingInfo = fetchParams.timingInfo + + // 16. Set timingInfo’s redirect end time and post-redirect start time to the + // coarsened shared current time given fetchParams’s cross-origin isolated + // capability. + timingInfo.redirectEndTime = timingInfo.postRedirectStartTime = + coarsenedSharedCurrentTime(fetchParams.crossOriginIsolatedCapability) + + // 17. If timingInfo’s redirect start time is 0, then set timingInfo’s + // redirect start time to timingInfo’s start time. + if (timingInfo.redirectStartTime === 0) { + timingInfo.redirectStartTime = timingInfo.startTime + } + + // 18. Append locationURL to request’s URL list. + request.urlList.push(locationURL) + + // 19. Invoke set request’s referrer policy on redirect on request and + // actualResponse. + setRequestReferrerPolicyOnRedirect(request, actualResponse) + + // 20. Return the result of running main fetch given fetchParams and true. + return mainFetch(fetchParams, true) +} + +// https://fetch.spec.whatwg.org/#http-network-or-cache-fetch +async function httpNetworkOrCacheFetch ( + fetchParams, + isAuthenticationFetch = false, + isNewConnectionFetch = false +) { + // 1. Let request be fetchParams’s request. + const request = fetchParams.request + + // 2. Let httpFetchParams be null. + let httpFetchParams = null + + // 3. Let httpRequest be null. + let httpRequest = null + + // 4. Let response be null. + let response = null + + // 5. Let storedResponse be null. + // TODO: cache + + // 6. Let httpCache be null. + const httpCache = null + + // 7. Let the revalidatingFlag be unset. + const revalidatingFlag = false + + // 8. Run these steps, but abort when the ongoing fetch is terminated: + + // 1. If request’s window is "no-window" and request’s redirect mode is + // "error", then set httpFetchParams to fetchParams and httpRequest to + // request. + if (request.window === 'no-window' && request.redirect === 'error') { + httpFetchParams = fetchParams + httpRequest = request + } else { + // Otherwise: + + // 1. Set httpRequest to a clone of request. + httpRequest = makeRequest(request) + + // 2. Set httpFetchParams to a copy of fetchParams. + httpFetchParams = { ...fetchParams } + + // 3. Set httpFetchParams’s request to httpRequest. + httpFetchParams.request = httpRequest + } + + // 3. Let includeCredentials be true if one of + const includeCredentials = + request.credentials === 'include' || + (request.credentials === 'same-origin' && + request.responseTainting === 'basic') + + // 4. Let contentLength be httpRequest’s body’s length, if httpRequest’s + // body is non-null; otherwise null. + const contentLength = httpRequest.body ? httpRequest.body.length : null + + // 5. Let contentLengthHeaderValue be null. + let contentLengthHeaderValue = null + + // 6. If httpRequest’s body is null and httpRequest’s method is `POST` or + // `PUT`, then set contentLengthHeaderValue to `0`. + if ( + httpRequest.body == null && + ['POST', 'PUT'].includes(httpRequest.method) + ) { + contentLengthHeaderValue = '0' + } + + // 7. If contentLength is non-null, then set contentLengthHeaderValue to + // contentLength, serialized and isomorphic encoded. + if (contentLength != null) { + contentLengthHeaderValue = isomorphicEncode(`${contentLength}`) + } + + // 8. If contentLengthHeaderValue is non-null, then append + // `Content-Length`/contentLengthHeaderValue to httpRequest’s header + // list. + if (contentLengthHeaderValue != null) { + httpRequest.headersList.append('content-length', contentLengthHeaderValue) + } + + // 9. If contentLengthHeaderValue is non-null, then append (`Content-Length`, + // contentLengthHeaderValue) to httpRequest’s header list. + + // 10. If contentLength is non-null and httpRequest’s keepalive is true, + // then: + if (contentLength != null && httpRequest.keepalive) { + // NOTE: keepalive is a noop outside of browser context. + } + + // 11. If httpRequest’s referrer is a URL, then append + // `Referer`/httpRequest’s referrer, serialized and isomorphic encoded, + // to httpRequest’s header list. + if (httpRequest.referrer instanceof URL) { + httpRequest.headersList.append('referer', isomorphicEncode(httpRequest.referrer.href)) + } + + // 12. Append a request `Origin` header for httpRequest. + appendRequestOriginHeader(httpRequest) + + // 13. Append the Fetch metadata headers for httpRequest. [FETCH-METADATA] + appendFetchMetadata(httpRequest) + + // 14. If httpRequest’s header list does not contain `User-Agent`, then + // user agents should append `User-Agent`/default `User-Agent` value to + // httpRequest’s header list. + if (!httpRequest.headersList.contains('user-agent')) { + httpRequest.headersList.append('user-agent', typeof esbuildDetection === 'undefined' ? 'undici' : 'node') + } + + // 15. If httpRequest’s cache mode is "default" and httpRequest’s header + // list contains `If-Modified-Since`, `If-None-Match`, + // `If-Unmodified-Since`, `If-Match`, or `If-Range`, then set + // httpRequest’s cache mode to "no-store". + if ( + httpRequest.cache === 'default' && + (httpRequest.headersList.contains('if-modified-since') || + httpRequest.headersList.contains('if-none-match') || + httpRequest.headersList.contains('if-unmodified-since') || + httpRequest.headersList.contains('if-match') || + httpRequest.headersList.contains('if-range')) + ) { + httpRequest.cache = 'no-store' + } + + // 16. If httpRequest’s cache mode is "no-cache", httpRequest’s prevent + // no-cache cache-control header modification flag is unset, and + // httpRequest’s header list does not contain `Cache-Control`, then append + // `Cache-Control`/`max-age=0` to httpRequest’s header list. + if ( + httpRequest.cache === 'no-cache' && + !httpRequest.preventNoCacheCacheControlHeaderModification && + !httpRequest.headersList.contains('cache-control') + ) { + httpRequest.headersList.append('cache-control', 'max-age=0') + } + + // 17. If httpRequest’s cache mode is "no-store" or "reload", then: + if (httpRequest.cache === 'no-store' || httpRequest.cache === 'reload') { + // 1. If httpRequest’s header list does not contain `Pragma`, then append + // `Pragma`/`no-cache` to httpRequest’s header list. + if (!httpRequest.headersList.contains('pragma')) { + httpRequest.headersList.append('pragma', 'no-cache') + } + + // 2. If httpRequest’s header list does not contain `Cache-Control`, + // then append `Cache-Control`/`no-cache` to httpRequest’s header list. + if (!httpRequest.headersList.contains('cache-control')) { + httpRequest.headersList.append('cache-control', 'no-cache') + } + } + + // 18. If httpRequest’s header list contains `Range`, then append + // `Accept-Encoding`/`identity` to httpRequest’s header list. + if (httpRequest.headersList.contains('range')) { + httpRequest.headersList.append('accept-encoding', 'identity') + } + + // 19. Modify httpRequest’s header list per HTTP. Do not append a given + // header if httpRequest’s header list contains that header’s name. + // TODO: https://github.com/whatwg/fetch/issues/1285#issuecomment-896560129 + if (!httpRequest.headersList.contains('accept-encoding')) { + if (urlHasHttpsScheme(requestCurrentURL(httpRequest))) { + httpRequest.headersList.append('accept-encoding', 'br, gzip, deflate') + } else { + httpRequest.headersList.append('accept-encoding', 'gzip, deflate') + } + } + + httpRequest.headersList.delete('host') + + // 20. If includeCredentials is true, then: + if (includeCredentials) { + // 1. If the user agent is not configured to block cookies for httpRequest + // (see section 7 of [COOKIES]), then: + // TODO: credentials + // 2. If httpRequest’s header list does not contain `Authorization`, then: + // TODO: credentials + } + + // 21. If there’s a proxy-authentication entry, use it as appropriate. + // TODO: proxy-authentication + + // 22. Set httpCache to the result of determining the HTTP cache + // partition, given httpRequest. + // TODO: cache + + // 23. If httpCache is null, then set httpRequest’s cache mode to + // "no-store". + if (httpCache == null) { + httpRequest.cache = 'no-store' + } + + // 24. If httpRequest’s cache mode is neither "no-store" nor "reload", + // then: + if (httpRequest.mode !== 'no-store' && httpRequest.mode !== 'reload') { + // TODO: cache + } + + // 9. If aborted, then return the appropriate network error for fetchParams. + // TODO + + // 10. If response is null, then: + if (response == null) { + // 1. If httpRequest’s cache mode is "only-if-cached", then return a + // network error. + if (httpRequest.mode === 'only-if-cached') { + return makeNetworkError('only if cached') + } + + // 2. Let forwardResponse be the result of running HTTP-network fetch + // given httpFetchParams, includeCredentials, and isNewConnectionFetch. + const forwardResponse = await httpNetworkFetch( + httpFetchParams, + includeCredentials, + isNewConnectionFetch + ) + + // 3. If httpRequest’s method is unsafe and forwardResponse’s status is + // in the range 200 to 399, inclusive, invalidate appropriate stored + // responses in httpCache, as per the "Invalidation" chapter of HTTP + // Caching, and set storedResponse to null. [HTTP-CACHING] + if ( + !safeMethodsSet.has(httpRequest.method) && + forwardResponse.status >= 200 && + forwardResponse.status <= 399 + ) { + // TODO: cache + } + + // 4. If the revalidatingFlag is set and forwardResponse’s status is 304, + // then: + if (revalidatingFlag && forwardResponse.status === 304) { + // TODO: cache + } + + // 5. If response is null, then: + if (response == null) { + // 1. Set response to forwardResponse. + response = forwardResponse + + // 2. Store httpRequest and forwardResponse in httpCache, as per the + // "Storing Responses in Caches" chapter of HTTP Caching. [HTTP-CACHING] + // TODO: cache + } + } + + // 11. Set response’s URL list to a clone of httpRequest’s URL list. + response.urlList = [...httpRequest.urlList] + + // 12. If httpRequest’s header list contains `Range`, then set response’s + // range-requested flag. + if (httpRequest.headersList.contains('range')) { + response.rangeRequested = true + } + + // 13. Set response’s request-includes-credentials to includeCredentials. + response.requestIncludesCredentials = includeCredentials + + // 14. If response’s status is 401, httpRequest’s response tainting is not + // "cors", includeCredentials is true, and request’s window is an environment + // settings object, then: + // TODO + + // 15. If response’s status is 407, then: + if (response.status === 407) { + // 1. If request’s window is "no-window", then return a network error. + if (request.window === 'no-window') { + return makeNetworkError() + } + + // 2. ??? + + // 3. If fetchParams is canceled, then return the appropriate network error for fetchParams. + if (isCancelled(fetchParams)) { + return makeAppropriateNetworkError(fetchParams) + } + + // 4. Prompt the end user as appropriate in request’s window and store + // the result as a proxy-authentication entry. [HTTP-AUTH] + // TODO: Invoke some kind of callback? + + // 5. Set response to the result of running HTTP-network-or-cache fetch given + // fetchParams. + // TODO + return makeNetworkError('proxy authentication required') + } + + // 16. If all of the following are true + if ( + // response’s status is 421 + response.status === 421 && + // isNewConnectionFetch is false + !isNewConnectionFetch && + // request’s body is null, or request’s body is non-null and request’s body’s source is non-null + (request.body == null || request.body.source != null) + ) { + // then: + + // 1. If fetchParams is canceled, then return the appropriate network error for fetchParams. + if (isCancelled(fetchParams)) { + return makeAppropriateNetworkError(fetchParams) + } + + // 2. Set response to the result of running HTTP-network-or-cache + // fetch given fetchParams, isAuthenticationFetch, and true. + + // TODO (spec): The spec doesn't specify this but we need to cancel + // the active response before we can start a new one. + // https://github.com/whatwg/fetch/issues/1293 + fetchParams.controller.connection.destroy() + + response = await httpNetworkOrCacheFetch( + fetchParams, + isAuthenticationFetch, + true + ) + } + + // 17. If isAuthenticationFetch is true, then create an authentication entry + if (isAuthenticationFetch) { + // TODO + } + + // 18. Return response. + return response +} + +// https://fetch.spec.whatwg.org/#http-network-fetch +async function httpNetworkFetch ( + fetchParams, + includeCredentials = false, + forceNewConnection = false +) { + assert(!fetchParams.controller.connection || fetchParams.controller.connection.destroyed) + + fetchParams.controller.connection = { + abort: null, + destroyed: false, + destroy (err) { + if (!this.destroyed) { + this.destroyed = true + this.abort?.(err ?? new DOMException('The operation was aborted.', 'AbortError')) + } + } + } + + // 1. Let request be fetchParams’s request. + const request = fetchParams.request + + // 2. Let response be null. + let response = null + + // 3. Let timingInfo be fetchParams’s timing info. + const timingInfo = fetchParams.timingInfo + + // 4. Let httpCache be the result of determining the HTTP cache partition, + // given request. + // TODO: cache + const httpCache = null + + // 5. If httpCache is null, then set request’s cache mode to "no-store". + if (httpCache == null) { + request.cache = 'no-store' + } + + // 6. Let networkPartitionKey be the result of determining the network + // partition key given request. + // TODO + + // 7. Let newConnection be "yes" if forceNewConnection is true; otherwise + // "no". + const newConnection = forceNewConnection ? 'yes' : 'no' // eslint-disable-line no-unused-vars + + // 8. Switch on request’s mode: + if (request.mode === 'websocket') { + // Let connection be the result of obtaining a WebSocket connection, + // given request’s current URL. + // TODO + } else { + // Let connection be the result of obtaining a connection, given + // networkPartitionKey, request’s current URL’s origin, + // includeCredentials, and forceNewConnection. + // TODO + } + + // 9. Run these steps, but abort when the ongoing fetch is terminated: + + // 1. If connection is failure, then return a network error. + + // 2. Set timingInfo’s final connection timing info to the result of + // calling clamp and coarsen connection timing info with connection’s + // timing info, timingInfo’s post-redirect start time, and fetchParams’s + // cross-origin isolated capability. + + // 3. If connection is not an HTTP/2 connection, request’s body is non-null, + // and request’s body’s source is null, then append (`Transfer-Encoding`, + // `chunked`) to request’s header list. + + // 4. Set timingInfo’s final network-request start time to the coarsened + // shared current time given fetchParams’s cross-origin isolated + // capability. + + // 5. Set response to the result of making an HTTP request over connection + // using request with the following caveats: + + // - Follow the relevant requirements from HTTP. [HTTP] [HTTP-SEMANTICS] + // [HTTP-COND] [HTTP-CACHING] [HTTP-AUTH] + + // - If request’s body is non-null, and request’s body’s source is null, + // then the user agent may have a buffer of up to 64 kibibytes and store + // a part of request’s body in that buffer. If the user agent reads from + // request’s body beyond that buffer’s size and the user agent needs to + // resend request, then instead return a network error. + + // - Set timingInfo’s final network-response start time to the coarsened + // shared current time given fetchParams’s cross-origin isolated capability, + // immediately after the user agent’s HTTP parser receives the first byte + // of the response (e.g., frame header bytes for HTTP/2 or response status + // line for HTTP/1.x). + + // - Wait until all the headers are transmitted. + + // - Any responses whose status is in the range 100 to 199, inclusive, + // and is not 101, are to be ignored, except for the purposes of setting + // timingInfo’s final network-response start time above. + + // - If request’s header list contains `Transfer-Encoding`/`chunked` and + // response is transferred via HTTP/1.0 or older, then return a network + // error. + + // - If the HTTP request results in a TLS client certificate dialog, then: + + // 1. If request’s window is an environment settings object, make the + // dialog available in request’s window. + + // 2. Otherwise, return a network error. + + // To transmit request’s body body, run these steps: + let requestBody = null + // 1. If body is null and fetchParams’s process request end-of-body is + // non-null, then queue a fetch task given fetchParams’s process request + // end-of-body and fetchParams’s task destination. + if (request.body == null && fetchParams.processRequestEndOfBody) { + queueMicrotask(() => fetchParams.processRequestEndOfBody()) + } else if (request.body != null) { + // 2. Otherwise, if body is non-null: + + // 1. Let processBodyChunk given bytes be these steps: + const processBodyChunk = async function * (bytes) { + // 1. If the ongoing fetch is terminated, then abort these steps. + if (isCancelled(fetchParams)) { + return + } + + // 2. Run this step in parallel: transmit bytes. + yield bytes + + // 3. If fetchParams’s process request body is non-null, then run + // fetchParams’s process request body given bytes’s length. + fetchParams.processRequestBodyChunkLength?.(bytes.byteLength) + } + + // 2. Let processEndOfBody be these steps: + const processEndOfBody = () => { + // 1. If fetchParams is canceled, then abort these steps. + if (isCancelled(fetchParams)) { + return + } + + // 2. If fetchParams’s process request end-of-body is non-null, + // then run fetchParams’s process request end-of-body. + if (fetchParams.processRequestEndOfBody) { + fetchParams.processRequestEndOfBody() + } + } + + // 3. Let processBodyError given e be these steps: + const processBodyError = (e) => { + // 1. If fetchParams is canceled, then abort these steps. + if (isCancelled(fetchParams)) { + return + } + + // 2. If e is an "AbortError" DOMException, then abort fetchParams’s controller. + if (e.name === 'AbortError') { + fetchParams.controller.abort() + } else { + fetchParams.controller.terminate(e) + } + } + + // 4. Incrementally read request’s body given processBodyChunk, processEndOfBody, + // processBodyError, and fetchParams’s task destination. + requestBody = (async function * () { + try { + for await (const bytes of request.body.stream) { + yield * processBodyChunk(bytes) + } + processEndOfBody() + } catch (err) { + processBodyError(err) + } + })() + } + + try { + // socket is only provided for websockets + const { body, status, statusText, headersList, socket } = await dispatch({ body: requestBody }) + + if (socket) { + response = makeResponse({ status, statusText, headersList, socket }) + } else { + const iterator = body[Symbol.asyncIterator]() + fetchParams.controller.next = () => iterator.next() + + response = makeResponse({ status, statusText, headersList }) + } + } catch (err) { + // 10. If aborted, then: + if (err.name === 'AbortError') { + // 1. If connection uses HTTP/2, then transmit an RST_STREAM frame. + fetchParams.controller.connection.destroy() + + // 2. Return the appropriate network error for fetchParams. + return makeAppropriateNetworkError(fetchParams, err) + } + + return makeNetworkError(err) + } + + // 11. Let pullAlgorithm be an action that resumes the ongoing fetch + // if it is suspended. + const pullAlgorithm = () => { + fetchParams.controller.resume() + } + + // 12. Let cancelAlgorithm be an algorithm that aborts fetchParams’s + // controller with reason, given reason. + const cancelAlgorithm = (reason) => { + fetchParams.controller.abort(reason) + } + + // 13. Let highWaterMark be a non-negative, non-NaN number, chosen by + // the user agent. + // TODO + + // 14. Let sizeAlgorithm be an algorithm that accepts a chunk object + // and returns a non-negative, non-NaN, non-infinite number, chosen by the user agent. + // TODO + + // 15. Let stream be a new ReadableStream. + // 16. Set up stream with pullAlgorithm set to pullAlgorithm, + // cancelAlgorithm set to cancelAlgorithm, highWaterMark set to + // highWaterMark, and sizeAlgorithm set to sizeAlgorithm. + if (!ReadableStream) { + ReadableStream = (__nccwpck_require__(5356).ReadableStream) + } + + const stream = new ReadableStream( + { + async start (controller) { + fetchParams.controller.controller = controller + }, + async pull (controller) { + await pullAlgorithm(controller) + }, + async cancel (reason) { + await cancelAlgorithm(reason) + } + }, + { + highWaterMark: 0, + size () { + return 1 + } + } + ) + + // 17. Run these steps, but abort when the ongoing fetch is terminated: + + // 1. Set response’s body to a new body whose stream is stream. + response.body = { stream } + + // 2. If response is not a network error and request’s cache mode is + // not "no-store", then update response in httpCache for request. + // TODO + + // 3. If includeCredentials is true and the user agent is not configured + // to block cookies for request (see section 7 of [COOKIES]), then run the + // "set-cookie-string" parsing algorithm (see section 5.2 of [COOKIES]) on + // the value of each header whose name is a byte-case-insensitive match for + // `Set-Cookie` in response’s header list, if any, and request’s current URL. + // TODO + + // 18. If aborted, then: + // TODO + + // 19. Run these steps in parallel: + + // 1. Run these steps, but abort when fetchParams is canceled: + fetchParams.controller.on('terminated', onAborted) + fetchParams.controller.resume = async () => { + // 1. While true + while (true) { + // 1-3. See onData... + + // 4. Set bytes to the result of handling content codings given + // codings and bytes. + let bytes + let isFailure + try { + const { done, value } = await fetchParams.controller.next() + + if (isAborted(fetchParams)) { + break + } + + bytes = done ? undefined : value + } catch (err) { + if (fetchParams.controller.ended && !timingInfo.encodedBodySize) { + // zlib doesn't like empty streams. + bytes = undefined + } else { + bytes = err + + // err may be propagated from the result of calling readablestream.cancel, + // which might not be an error. https://github.com/nodejs/undici/issues/2009 + isFailure = true + } + } + + if (bytes === undefined) { + // 2. Otherwise, if the bytes transmission for response’s message + // body is done normally and stream is readable, then close + // stream, finalize response for fetchParams and response, and + // abort these in-parallel steps. + readableStreamClose(fetchParams.controller.controller) + + finalizeResponse(fetchParams, response) + + return + } + + // 5. Increase timingInfo’s decoded body size by bytes’s length. + timingInfo.decodedBodySize += bytes?.byteLength ?? 0 + + // 6. If bytes is failure, then terminate fetchParams’s controller. + if (isFailure) { + fetchParams.controller.terminate(bytes) + return + } + + // 7. Enqueue a Uint8Array wrapping an ArrayBuffer containing bytes + // into stream. + fetchParams.controller.controller.enqueue(new Uint8Array(bytes)) + + // 8. If stream is errored, then terminate the ongoing fetch. + if (isErrored(stream)) { + fetchParams.controller.terminate() + return + } + + // 9. If stream doesn’t need more data ask the user agent to suspend + // the ongoing fetch. + if (!fetchParams.controller.controller.desiredSize) { + return + } + } + } + + // 2. If aborted, then: + function onAborted (reason) { + // 2. If fetchParams is aborted, then: + if (isAborted(fetchParams)) { + // 1. Set response’s aborted flag. + response.aborted = true + + // 2. If stream is readable, then error stream with the result of + // deserialize a serialized abort reason given fetchParams’s + // controller’s serialized abort reason and an + // implementation-defined realm. + if (isReadable(stream)) { + fetchParams.controller.controller.error( + fetchParams.controller.serializedAbortReason + ) + } + } else { + // 3. Otherwise, if stream is readable, error stream with a TypeError. + if (isReadable(stream)) { + fetchParams.controller.controller.error(new TypeError('terminated', { + cause: isErrorLike(reason) ? reason : undefined + })) + } + } + + // 4. If connection uses HTTP/2, then transmit an RST_STREAM frame. + // 5. Otherwise, the user agent should close connection unless it would be bad for performance to do so. + fetchParams.controller.connection.destroy() + } + + // 20. Return response. + return response + + async function dispatch ({ body }) { + const url = requestCurrentURL(request) + /** @type {import('../..').Agent} */ + const agent = fetchParams.controller.dispatcher + + return new Promise((resolve, reject) => agent.dispatch( + { + path: url.pathname + url.search, + origin: url.origin, + method: request.method, + body: fetchParams.controller.dispatcher.isMockActive ? request.body && (request.body.source || request.body.stream) : body, + headers: request.headersList.entries, + maxRedirections: 0, + upgrade: request.mode === 'websocket' ? 'websocket' : undefined + }, + { + body: null, + abort: null, + + onConnect (abort) { + // TODO (fix): Do we need connection here? + const { connection } = fetchParams.controller + + if (connection.destroyed) { + abort(new DOMException('The operation was aborted.', 'AbortError')) + } else { + fetchParams.controller.on('terminated', abort) + this.abort = connection.abort = abort + } + }, + + onHeaders (status, headersList, resume, statusText) { + if (status < 200) { + return + } + + let codings = [] + let location = '' + + const headers = new Headers() + + // For H2, the headers are a plain JS object + // We distinguish between them and iterate accordingly + if (Array.isArray(headersList)) { + for (let n = 0; n < headersList.length; n += 2) { + const key = headersList[n + 0].toString('latin1') + const val = headersList[n + 1].toString('latin1') + if (key.toLowerCase() === 'content-encoding') { + // https://www.rfc-editor.org/rfc/rfc7231#section-3.1.2.1 + // "All content-coding values are case-insensitive..." + codings = val.toLowerCase().split(',').map((x) => x.trim()) + } else if (key.toLowerCase() === 'location') { + location = val + } + + headers[kHeadersList].append(key, val) + } + } else { + const keys = Object.keys(headersList) + for (const key of keys) { + const val = headersList[key] + if (key.toLowerCase() === 'content-encoding') { + // https://www.rfc-editor.org/rfc/rfc7231#section-3.1.2.1 + // "All content-coding values are case-insensitive..." + codings = val.toLowerCase().split(',').map((x) => x.trim()).reverse() + } else if (key.toLowerCase() === 'location') { + location = val + } + + headers[kHeadersList].append(key, val) + } + } + + this.body = new Readable({ read: resume }) + + const decoders = [] + + const willFollow = request.redirect === 'follow' && + location && + redirectStatusSet.has(status) + + // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding + if (request.method !== 'HEAD' && request.method !== 'CONNECT' && !nullBodyStatus.includes(status) && !willFollow) { + for (const coding of codings) { + // https://www.rfc-editor.org/rfc/rfc9112.html#section-7.2 + if (coding === 'x-gzip' || coding === 'gzip') { + decoders.push(zlib.createGunzip({ + // Be less strict when decoding compressed responses, since sometimes + // servers send slightly invalid responses that are still accepted + // by common browsers. + // Always using Z_SYNC_FLUSH is what cURL does. + flush: zlib.constants.Z_SYNC_FLUSH, + finishFlush: zlib.constants.Z_SYNC_FLUSH + })) + } else if (coding === 'deflate') { + decoders.push(zlib.createInflate()) + } else if (coding === 'br') { + decoders.push(zlib.createBrotliDecompress()) + } else { + decoders.length = 0 + break + } + } + } + + resolve({ + status, + statusText, + headersList: headers[kHeadersList], + body: decoders.length + ? pipeline(this.body, ...decoders, () => { }) + : this.body.on('error', () => {}) + }) + + return true + }, + + onData (chunk) { + if (fetchParams.controller.dump) { + return + } + + // 1. If one or more bytes have been transmitted from response’s + // message body, then: + + // 1. Let bytes be the transmitted bytes. + const bytes = chunk + + // 2. Let codings be the result of extracting header list values + // given `Content-Encoding` and response’s header list. + // See pullAlgorithm. + + // 3. Increase timingInfo’s encoded body size by bytes’s length. + timingInfo.encodedBodySize += bytes.byteLength + + // 4. See pullAlgorithm... + + return this.body.push(bytes) + }, + + onComplete () { + if (this.abort) { + fetchParams.controller.off('terminated', this.abort) + } + + fetchParams.controller.ended = true + + this.body.push(null) + }, + + onError (error) { + if (this.abort) { + fetchParams.controller.off('terminated', this.abort) + } + + this.body?.destroy(error) + + fetchParams.controller.terminate(error) + + reject(error) + }, + + onUpgrade (status, headersList, socket) { + if (status !== 101) { + return + } + + const headers = new Headers() + + for (let n = 0; n < headersList.length; n += 2) { + const key = headersList[n + 0].toString('latin1') + const val = headersList[n + 1].toString('latin1') + + headers[kHeadersList].append(key, val) + } + + resolve({ + status, + statusText: STATUS_CODES[status], + headersList: headers[kHeadersList], + socket + }) + + return true + } + } + )) + } +} + +module.exports = { + fetch, + Fetch, + fetching, + finalizeAndReportTiming +} + + +/***/ }), + +/***/ 9157: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; +/* globals AbortController */ + + + +const { extractBody, mixinBody, cloneBody } = __nccwpck_require__(804) +const { Headers, fill: fillHeaders, HeadersList } = __nccwpck_require__(7689) +const { FinalizationRegistry } = __nccwpck_require__(231)() +const util = __nccwpck_require__(9522) +const { + isValidHTTPToken, + sameOrigin, + normalizeMethod, + makePolicyContainer, + normalizeMethodRecord +} = __nccwpck_require__(784) +const { + forbiddenMethodsSet, + corsSafeListedMethodsSet, + referrerPolicy, + requestRedirect, + requestMode, + requestCredentials, + requestCache, + requestDuplex +} = __nccwpck_require__(7059) +const { kEnumerableProperty } = util +const { kHeaders, kSignal, kState, kGuard, kRealm } = __nccwpck_require__(8085) +const { webidl } = __nccwpck_require__(1537) +const { getGlobalOrigin } = __nccwpck_require__(5799) +const { URLSerializer } = __nccwpck_require__(2791) +const { kHeadersList } = __nccwpck_require__(9440) +const assert = __nccwpck_require__(9491) +const { getMaxListeners, setMaxListeners, getEventListeners, defaultMaxListeners } = __nccwpck_require__(2361) + +let TransformStream = globalThis.TransformStream + +const kInit = Symbol('init') +const kAbortController = Symbol('abortController') + +const requestFinalizer = new FinalizationRegistry(({ signal, abort }) => { + signal.removeEventListener('abort', abort) +}) + +// https://fetch.spec.whatwg.org/#request-class +class Request { + // https://fetch.spec.whatwg.org/#dom-request + constructor (input, init = {}) { + if (input === kInit) { + return + } + + webidl.argumentLengthCheck(arguments, 1, { header: 'Request constructor' }) + + input = webidl.converters.RequestInfo(input) + init = webidl.converters.RequestInit(init) + + // https://html.spec.whatwg.org/multipage/webappapis.html#environment-settings-object + this[kRealm] = { + settingsObject: { + baseUrl: getGlobalOrigin(), + get origin () { + return this.baseUrl?.origin + }, + policyContainer: makePolicyContainer() + } + } + + // 1. Let request be null. + let request = null + + // 2. Let fallbackMode be null. + let fallbackMode = null + + // 3. Let baseURL be this’s relevant settings object’s API base URL. + const baseUrl = this[kRealm].settingsObject.baseUrl + + // 4. Let signal be null. + let signal = null + + // 5. If input is a string, then: + if (typeof input === 'string') { + // 1. Let parsedURL be the result of parsing input with baseURL. + // 2. If parsedURL is failure, then throw a TypeError. + let parsedURL + try { + parsedURL = new URL(input, baseUrl) + } catch (err) { + throw new TypeError('Failed to parse URL from ' + input, { cause: err }) + } + + // 3. If parsedURL includes credentials, then throw a TypeError. + if (parsedURL.username || parsedURL.password) { + throw new TypeError( + 'Request cannot be constructed from a URL that includes credentials: ' + + input + ) + } + + // 4. Set request to a new request whose URL is parsedURL. + request = makeRequest({ urlList: [parsedURL] }) + + // 5. Set fallbackMode to "cors". + fallbackMode = 'cors' + } else { + // 6. Otherwise: + + // 7. Assert: input is a Request object. + assert(input instanceof Request) + + // 8. Set request to input’s request. + request = input[kState] + + // 9. Set signal to input’s signal. + signal = input[kSignal] + } + + // 7. Let origin be this’s relevant settings object’s origin. + const origin = this[kRealm].settingsObject.origin + + // 8. Let window be "client". + let window = 'client' + + // 9. If request’s window is an environment settings object and its origin + // is same origin with origin, then set window to request’s window. + if ( + request.window?.constructor?.name === 'EnvironmentSettingsObject' && + sameOrigin(request.window, origin) + ) { + window = request.window + } + + // 10. If init["window"] exists and is non-null, then throw a TypeError. + if (init.window != null) { + throw new TypeError(`'window' option '${window}' must be null`) + } + + // 11. If init["window"] exists, then set window to "no-window". + if ('window' in init) { + window = 'no-window' + } + + // 12. Set request to a new request with the following properties: + request = makeRequest({ + // URL request’s URL. + // undici implementation note: this is set as the first item in request's urlList in makeRequest + // method request’s method. + method: request.method, + // header list A copy of request’s header list. + // undici implementation note: headersList is cloned in makeRequest + headersList: request.headersList, + // unsafe-request flag Set. + unsafeRequest: request.unsafeRequest, + // client This’s relevant settings object. + client: this[kRealm].settingsObject, + // window window. + window, + // priority request’s priority. + priority: request.priority, + // origin request’s origin. The propagation of the origin is only significant for navigation requests + // being handled by a service worker. In this scenario a request can have an origin that is different + // from the current client. + origin: request.origin, + // referrer request’s referrer. + referrer: request.referrer, + // referrer policy request’s referrer policy. + referrerPolicy: request.referrerPolicy, + // mode request’s mode. + mode: request.mode, + // credentials mode request’s credentials mode. + credentials: request.credentials, + // cache mode request’s cache mode. + cache: request.cache, + // redirect mode request’s redirect mode. + redirect: request.redirect, + // integrity metadata request’s integrity metadata. + integrity: request.integrity, + // keepalive request’s keepalive. + keepalive: request.keepalive, + // reload-navigation flag request’s reload-navigation flag. + reloadNavigation: request.reloadNavigation, + // history-navigation flag request’s history-navigation flag. + historyNavigation: request.historyNavigation, + // URL list A clone of request’s URL list. + urlList: [...request.urlList] + }) + + const initHasKey = Object.keys(init).length !== 0 + + // 13. If init is not empty, then: + if (initHasKey) { + // 1. If request’s mode is "navigate", then set it to "same-origin". + if (request.mode === 'navigate') { + request.mode = 'same-origin' + } + + // 2. Unset request’s reload-navigation flag. + request.reloadNavigation = false + + // 3. Unset request’s history-navigation flag. + request.historyNavigation = false + + // 4. Set request’s origin to "client". + request.origin = 'client' + + // 5. Set request’s referrer to "client" + request.referrer = 'client' + + // 6. Set request’s referrer policy to the empty string. + request.referrerPolicy = '' + + // 7. Set request’s URL to request’s current URL. + request.url = request.urlList[request.urlList.length - 1] + + // 8. Set request’s URL list to « request’s URL ». + request.urlList = [request.url] + } + + // 14. If init["referrer"] exists, then: + if (init.referrer !== undefined) { + // 1. Let referrer be init["referrer"]. + const referrer = init.referrer + + // 2. If referrer is the empty string, then set request’s referrer to "no-referrer". + if (referrer === '') { + request.referrer = 'no-referrer' + } else { + // 1. Let parsedReferrer be the result of parsing referrer with + // baseURL. + // 2. If parsedReferrer is failure, then throw a TypeError. + let parsedReferrer + try { + parsedReferrer = new URL(referrer, baseUrl) + } catch (err) { + throw new TypeError(`Referrer "${referrer}" is not a valid URL.`, { cause: err }) + } + + // 3. If one of the following is true + // - parsedReferrer’s scheme is "about" and path is the string "client" + // - parsedReferrer’s origin is not same origin with origin + // then set request’s referrer to "client". + if ( + (parsedReferrer.protocol === 'about:' && parsedReferrer.hostname === 'client') || + (origin && !sameOrigin(parsedReferrer, this[kRealm].settingsObject.baseUrl)) + ) { + request.referrer = 'client' + } else { + // 4. Otherwise, set request’s referrer to parsedReferrer. + request.referrer = parsedReferrer + } + } + } + + // 15. If init["referrerPolicy"] exists, then set request’s referrer policy + // to it. + if (init.referrerPolicy !== undefined) { + request.referrerPolicy = init.referrerPolicy + } + + // 16. Let mode be init["mode"] if it exists, and fallbackMode otherwise. + let mode + if (init.mode !== undefined) { + mode = init.mode + } else { + mode = fallbackMode + } + + // 17. If mode is "navigate", then throw a TypeError. + if (mode === 'navigate') { + throw webidl.errors.exception({ + header: 'Request constructor', + message: 'invalid request mode navigate.' + }) + } + + // 18. If mode is non-null, set request’s mode to mode. + if (mode != null) { + request.mode = mode + } + + // 19. If init["credentials"] exists, then set request’s credentials mode + // to it. + if (init.credentials !== undefined) { + request.credentials = init.credentials + } + + // 18. If init["cache"] exists, then set request’s cache mode to it. + if (init.cache !== undefined) { + request.cache = init.cache + } + + // 21. If request’s cache mode is "only-if-cached" and request’s mode is + // not "same-origin", then throw a TypeError. + if (request.cache === 'only-if-cached' && request.mode !== 'same-origin') { + throw new TypeError( + "'only-if-cached' can be set only with 'same-origin' mode" + ) + } + + // 22. If init["redirect"] exists, then set request’s redirect mode to it. + if (init.redirect !== undefined) { + request.redirect = init.redirect + } + + // 23. If init["integrity"] exists, then set request’s integrity metadata to it. + if (init.integrity !== undefined && init.integrity != null) { + request.integrity = String(init.integrity) + } + + // 24. If init["keepalive"] exists, then set request’s keepalive to it. + if (init.keepalive !== undefined) { + request.keepalive = Boolean(init.keepalive) + } + + // 25. If init["method"] exists, then: + if (init.method !== undefined) { + // 1. Let method be init["method"]. + let method = init.method + + // 2. If method is not a method or method is a forbidden method, then + // throw a TypeError. + if (!isValidHTTPToken(method)) { + throw new TypeError(`'${method}' is not a valid HTTP method.`) + } + + if (forbiddenMethodsSet.has(method.toUpperCase())) { + throw new TypeError(`'${method}' HTTP method is unsupported.`) + } + + // 3. Normalize method. + method = normalizeMethodRecord[method] ?? normalizeMethod(method) + + // 4. Set request’s method to method. + request.method = method + } + + // 26. If init["signal"] exists, then set signal to it. + if (init.signal !== undefined) { + signal = init.signal + } + + // 27. Set this’s request to request. + this[kState] = request + + // 28. Set this’s signal to a new AbortSignal object with this’s relevant + // Realm. + // TODO: could this be simplified with AbortSignal.any + // (https://dom.spec.whatwg.org/#dom-abortsignal-any) + const ac = new AbortController() + this[kSignal] = ac.signal + this[kSignal][kRealm] = this[kRealm] + + // 29. If signal is not null, then make this’s signal follow signal. + if (signal != null) { + if ( + !signal || + typeof signal.aborted !== 'boolean' || + typeof signal.addEventListener !== 'function' + ) { + throw new TypeError( + "Failed to construct 'Request': member signal is not of type AbortSignal." + ) + } + + if (signal.aborted) { + ac.abort(signal.reason) + } else { + // Keep a strong ref to ac while request object + // is alive. This is needed to prevent AbortController + // from being prematurely garbage collected. + // See, https://github.com/nodejs/undici/issues/1926. + this[kAbortController] = ac + + const acRef = new WeakRef(ac) + const abort = function () { + const ac = acRef.deref() + if (ac !== undefined) { + ac.abort(this.reason) + } + } + + // Third-party AbortControllers may not work with these. + // See, https://github.com/nodejs/undici/pull/1910#issuecomment-1464495619. + try { + // If the max amount of listeners is equal to the default, increase it + // This is only available in node >= v19.9.0 + if (typeof getMaxListeners === 'function' && getMaxListeners(signal) === defaultMaxListeners) { + setMaxListeners(100, signal) + } else if (getEventListeners(signal, 'abort').length >= defaultMaxListeners) { + setMaxListeners(100, signal) + } + } catch {} + + util.addAbortListener(signal, abort) + requestFinalizer.register(ac, { signal, abort }) + } + } + + // 30. Set this’s headers to a new Headers object with this’s relevant + // Realm, whose header list is request’s header list and guard is + // "request". + this[kHeaders] = new Headers() + this[kHeaders][kHeadersList] = request.headersList + this[kHeaders][kGuard] = 'request' + this[kHeaders][kRealm] = this[kRealm] + + // 31. If this’s request’s mode is "no-cors", then: + if (mode === 'no-cors') { + // 1. If this’s request’s method is not a CORS-safelisted method, + // then throw a TypeError. + if (!corsSafeListedMethodsSet.has(request.method)) { + throw new TypeError( + `'${request.method} is unsupported in no-cors mode.` + ) + } + + // 2. Set this’s headers’s guard to "request-no-cors". + this[kHeaders][kGuard] = 'request-no-cors' + } + + // 32. If init is not empty, then: + if (initHasKey) { + /** @type {HeadersList} */ + const headersList = this[kHeaders][kHeadersList] + // 1. Let headers be a copy of this’s headers and its associated header + // list. + // 2. If init["headers"] exists, then set headers to init["headers"]. + const headers = init.headers !== undefined ? init.headers : new HeadersList(headersList) + + // 3. Empty this’s headers’s header list. + headersList.clear() + + // 4. If headers is a Headers object, then for each header in its header + // list, append header’s name/header’s value to this’s headers. + if (headers instanceof HeadersList) { + for (const [key, val] of headers) { + headersList.append(key, val) + } + // Note: Copy the `set-cookie` meta-data. + headersList.cookies = headers.cookies + } else { + // 5. Otherwise, fill this’s headers with headers. + fillHeaders(this[kHeaders], headers) + } + } + + // 33. Let inputBody be input’s request’s body if input is a Request + // object; otherwise null. + const inputBody = input instanceof Request ? input[kState].body : null + + // 34. If either init["body"] exists and is non-null or inputBody is + // non-null, and request’s method is `GET` or `HEAD`, then throw a + // TypeError. + if ( + (init.body != null || inputBody != null) && + (request.method === 'GET' || request.method === 'HEAD') + ) { + throw new TypeError('Request with GET/HEAD method cannot have body.') + } + + // 35. Let initBody be null. + let initBody = null + + // 36. If init["body"] exists and is non-null, then: + if (init.body != null) { + // 1. Let Content-Type be null. + // 2. Set initBody and Content-Type to the result of extracting + // init["body"], with keepalive set to request’s keepalive. + const [extractedBody, contentType] = extractBody( + init.body, + request.keepalive + ) + initBody = extractedBody + + // 3, If Content-Type is non-null and this’s headers’s header list does + // not contain `Content-Type`, then append `Content-Type`/Content-Type to + // this’s headers. + if (contentType && !this[kHeaders][kHeadersList].contains('content-type')) { + this[kHeaders].append('content-type', contentType) + } + } + + // 37. Let inputOrInitBody be initBody if it is non-null; otherwise + // inputBody. + const inputOrInitBody = initBody ?? inputBody + + // 38. If inputOrInitBody is non-null and inputOrInitBody’s source is + // null, then: + if (inputOrInitBody != null && inputOrInitBody.source == null) { + // 1. If initBody is non-null and init["duplex"] does not exist, + // then throw a TypeError. + if (initBody != null && init.duplex == null) { + throw new TypeError('RequestInit: duplex option is required when sending a body.') + } + + // 2. If this’s request’s mode is neither "same-origin" nor "cors", + // then throw a TypeError. + if (request.mode !== 'same-origin' && request.mode !== 'cors') { + throw new TypeError( + 'If request is made from ReadableStream, mode should be "same-origin" or "cors"' + ) + } + + // 3. Set this’s request’s use-CORS-preflight flag. + request.useCORSPreflightFlag = true + } + + // 39. Let finalBody be inputOrInitBody. + let finalBody = inputOrInitBody + + // 40. If initBody is null and inputBody is non-null, then: + if (initBody == null && inputBody != null) { + // 1. If input is unusable, then throw a TypeError. + if (util.isDisturbed(inputBody.stream) || inputBody.stream.locked) { + throw new TypeError( + 'Cannot construct a Request with a Request object that has already been used.' + ) + } + + // 2. Set finalBody to the result of creating a proxy for inputBody. + if (!TransformStream) { + TransformStream = (__nccwpck_require__(5356).TransformStream) + } + + // https://streams.spec.whatwg.org/#readablestream-create-a-proxy + const identityTransform = new TransformStream() + inputBody.stream.pipeThrough(identityTransform) + finalBody = { + source: inputBody.source, + length: inputBody.length, + stream: identityTransform.readable + } + } + + // 41. Set this’s request’s body to finalBody. + this[kState].body = finalBody + } + + // Returns request’s HTTP method, which is "GET" by default. + get method () { + webidl.brandCheck(this, Request) + + // The method getter steps are to return this’s request’s method. + return this[kState].method + } + + // Returns the URL of request as a string. + get url () { + webidl.brandCheck(this, Request) + + // The url getter steps are to return this’s request’s URL, serialized. + return URLSerializer(this[kState].url) + } + + // Returns a Headers object consisting of the headers associated with request. + // Note that headers added in the network layer by the user agent will not + // be accounted for in this object, e.g., the "Host" header. + get headers () { + webidl.brandCheck(this, Request) + + // The headers getter steps are to return this’s headers. + return this[kHeaders] + } + + // Returns the kind of resource requested by request, e.g., "document" + // or "script". + get destination () { + webidl.brandCheck(this, Request) + + // The destination getter are to return this’s request’s destination. + return this[kState].destination + } + + // Returns the referrer of request. Its value can be a same-origin URL if + // explicitly set in init, the empty string to indicate no referrer, and + // "about:client" when defaulting to the global’s default. This is used + // during fetching to determine the value of the `Referer` header of the + // request being made. + get referrer () { + webidl.brandCheck(this, Request) + + // 1. If this’s request’s referrer is "no-referrer", then return the + // empty string. + if (this[kState].referrer === 'no-referrer') { + return '' + } + + // 2. If this’s request’s referrer is "client", then return + // "about:client". + if (this[kState].referrer === 'client') { + return 'about:client' + } + + // Return this’s request’s referrer, serialized. + return this[kState].referrer.toString() + } + + // Returns the referrer policy associated with request. + // This is used during fetching to compute the value of the request’s + // referrer. + get referrerPolicy () { + webidl.brandCheck(this, Request) + + // The referrerPolicy getter steps are to return this’s request’s referrer policy. + return this[kState].referrerPolicy + } + + // Returns the mode associated with request, which is a string indicating + // whether the request will use CORS, or will be restricted to same-origin + // URLs. + get mode () { + webidl.brandCheck(this, Request) + + // The mode getter steps are to return this’s request’s mode. + return this[kState].mode + } + + // Returns the credentials mode associated with request, + // which is a string indicating whether credentials will be sent with the + // request always, never, or only when sent to a same-origin URL. + get credentials () { + // The credentials getter steps are to return this’s request’s credentials mode. + return this[kState].credentials + } + + // Returns the cache mode associated with request, + // which is a string indicating how the request will + // interact with the browser’s cache when fetching. + get cache () { + webidl.brandCheck(this, Request) + + // The cache getter steps are to return this’s request’s cache mode. + return this[kState].cache + } + + // Returns the redirect mode associated with request, + // which is a string indicating how redirects for the + // request will be handled during fetching. A request + // will follow redirects by default. + get redirect () { + webidl.brandCheck(this, Request) + + // The redirect getter steps are to return this’s request’s redirect mode. + return this[kState].redirect + } + + // Returns request’s subresource integrity metadata, which is a + // cryptographic hash of the resource being fetched. Its value + // consists of multiple hashes separated by whitespace. [SRI] + get integrity () { + webidl.brandCheck(this, Request) + + // The integrity getter steps are to return this’s request’s integrity + // metadata. + return this[kState].integrity + } + + // Returns a boolean indicating whether or not request can outlive the + // global in which it was created. + get keepalive () { + webidl.brandCheck(this, Request) + + // The keepalive getter steps are to return this’s request’s keepalive. + return this[kState].keepalive + } + + // Returns a boolean indicating whether or not request is for a reload + // navigation. + get isReloadNavigation () { + webidl.brandCheck(this, Request) + + // The isReloadNavigation getter steps are to return true if this’s + // request’s reload-navigation flag is set; otherwise false. + return this[kState].reloadNavigation + } + + // Returns a boolean indicating whether or not request is for a history + // navigation (a.k.a. back-foward navigation). + get isHistoryNavigation () { + webidl.brandCheck(this, Request) + + // The isHistoryNavigation getter steps are to return true if this’s request’s + // history-navigation flag is set; otherwise false. + return this[kState].historyNavigation + } + + // Returns the signal associated with request, which is an AbortSignal + // object indicating whether or not request has been aborted, and its + // abort event handler. + get signal () { + webidl.brandCheck(this, Request) + + // The signal getter steps are to return this’s signal. + return this[kSignal] + } + + get body () { + webidl.brandCheck(this, Request) + + return this[kState].body ? this[kState].body.stream : null + } + + get bodyUsed () { + webidl.brandCheck(this, Request) + + return !!this[kState].body && util.isDisturbed(this[kState].body.stream) + } + + get duplex () { + webidl.brandCheck(this, Request) + + return 'half' + } + + // Returns a clone of request. + clone () { + webidl.brandCheck(this, Request) + + // 1. If this is unusable, then throw a TypeError. + if (this.bodyUsed || this.body?.locked) { + throw new TypeError('unusable') + } + + // 2. Let clonedRequest be the result of cloning this’s request. + const clonedRequest = cloneRequest(this[kState]) + + // 3. Let clonedRequestObject be the result of creating a Request object, + // given clonedRequest, this’s headers’s guard, and this’s relevant Realm. + const clonedRequestObject = new Request(kInit) + clonedRequestObject[kState] = clonedRequest + clonedRequestObject[kRealm] = this[kRealm] + clonedRequestObject[kHeaders] = new Headers() + clonedRequestObject[kHeaders][kHeadersList] = clonedRequest.headersList + clonedRequestObject[kHeaders][kGuard] = this[kHeaders][kGuard] + clonedRequestObject[kHeaders][kRealm] = this[kHeaders][kRealm] + + // 4. Make clonedRequestObject’s signal follow this’s signal. + const ac = new AbortController() + if (this.signal.aborted) { + ac.abort(this.signal.reason) + } else { + util.addAbortListener( + this.signal, + () => { + ac.abort(this.signal.reason) + } + ) + } + clonedRequestObject[kSignal] = ac.signal + + // 4. Return clonedRequestObject. + return clonedRequestObject + } +} + +mixinBody(Request) + +function makeRequest (init) { + // https://fetch.spec.whatwg.org/#requests + const request = { + method: 'GET', + localURLsOnly: false, + unsafeRequest: false, + body: null, + client: null, + reservedClient: null, + replacesClientId: '', + window: 'client', + keepalive: false, + serviceWorkers: 'all', + initiator: '', + destination: '', + priority: null, + origin: 'client', + policyContainer: 'client', + referrer: 'client', + referrerPolicy: '', + mode: 'no-cors', + useCORSPreflightFlag: false, + credentials: 'same-origin', + useCredentials: false, + cache: 'default', + redirect: 'follow', + integrity: '', + cryptoGraphicsNonceMetadata: '', + parserMetadata: '', + reloadNavigation: false, + historyNavigation: false, + userActivation: false, + taintedOrigin: false, + redirectCount: 0, + responseTainting: 'basic', + preventNoCacheCacheControlHeaderModification: false, + done: false, + timingAllowFailed: false, + ...init, + headersList: init.headersList + ? new HeadersList(init.headersList) + : new HeadersList() + } + request.url = request.urlList[0] + return request +} + +// https://fetch.spec.whatwg.org/#concept-request-clone +function cloneRequest (request) { + // To clone a request request, run these steps: + + // 1. Let newRequest be a copy of request, except for its body. + const newRequest = makeRequest({ ...request, body: null }) + + // 2. If request’s body is non-null, set newRequest’s body to the + // result of cloning request’s body. + if (request.body != null) { + newRequest.body = cloneBody(request.body) + } + + // 3. Return newRequest. + return newRequest +} + +Object.defineProperties(Request.prototype, { + method: kEnumerableProperty, + url: kEnumerableProperty, + headers: kEnumerableProperty, + redirect: kEnumerableProperty, + clone: kEnumerableProperty, + signal: kEnumerableProperty, + duplex: kEnumerableProperty, + destination: kEnumerableProperty, + body: kEnumerableProperty, + bodyUsed: kEnumerableProperty, + isHistoryNavigation: kEnumerableProperty, + isReloadNavigation: kEnumerableProperty, + keepalive: kEnumerableProperty, + integrity: kEnumerableProperty, + cache: kEnumerableProperty, + credentials: kEnumerableProperty, + attribute: kEnumerableProperty, + referrerPolicy: kEnumerableProperty, + referrer: kEnumerableProperty, + mode: kEnumerableProperty, + [Symbol.toStringTag]: { + value: 'Request', + configurable: true + } +}) + +webidl.converters.Request = webidl.interfaceConverter( + Request +) + +// https://fetch.spec.whatwg.org/#requestinfo +webidl.converters.RequestInfo = function (V) { + if (typeof V === 'string') { + return webidl.converters.USVString(V) + } + + if (V instanceof Request) { + return webidl.converters.Request(V) + } + + return webidl.converters.USVString(V) +} + +webidl.converters.AbortSignal = webidl.interfaceConverter( + AbortSignal +) + +// https://fetch.spec.whatwg.org/#requestinit +webidl.converters.RequestInit = webidl.dictionaryConverter([ + { + key: 'method', + converter: webidl.converters.ByteString + }, + { + key: 'headers', + converter: webidl.converters.HeadersInit + }, + { + key: 'body', + converter: webidl.nullableConverter( + webidl.converters.BodyInit + ) + }, + { + key: 'referrer', + converter: webidl.converters.USVString + }, + { + key: 'referrerPolicy', + converter: webidl.converters.DOMString, + // https://w3c.github.io/webappsec-referrer-policy/#referrer-policy + allowedValues: referrerPolicy + }, + { + key: 'mode', + converter: webidl.converters.DOMString, + // https://fetch.spec.whatwg.org/#concept-request-mode + allowedValues: requestMode + }, + { + key: 'credentials', + converter: webidl.converters.DOMString, + // https://fetch.spec.whatwg.org/#requestcredentials + allowedValues: requestCredentials + }, + { + key: 'cache', + converter: webidl.converters.DOMString, + // https://fetch.spec.whatwg.org/#requestcache + allowedValues: requestCache + }, + { + key: 'redirect', + converter: webidl.converters.DOMString, + // https://fetch.spec.whatwg.org/#requestredirect + allowedValues: requestRedirect + }, + { + key: 'integrity', + converter: webidl.converters.DOMString + }, + { + key: 'keepalive', + converter: webidl.converters.boolean + }, + { + key: 'signal', + converter: webidl.nullableConverter( + (signal) => webidl.converters.AbortSignal( + signal, + { strict: false } + ) + ) + }, + { + key: 'window', + converter: webidl.converters.any + }, + { + key: 'duplex', + converter: webidl.converters.DOMString, + allowedValues: requestDuplex + } +]) + +module.exports = { Request, makeRequest } + + +/***/ }), + +/***/ 5796: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { Headers, HeadersList, fill } = __nccwpck_require__(7689) +const { extractBody, cloneBody, mixinBody } = __nccwpck_require__(804) +const util = __nccwpck_require__(9522) +const { kEnumerableProperty } = util +const { + isValidReasonPhrase, + isCancelled, + isAborted, + isBlobLike, + serializeJavascriptValueToJSONString, + isErrorLike, + isomorphicEncode +} = __nccwpck_require__(784) +const { + redirectStatusSet, + nullBodyStatus, + DOMException +} = __nccwpck_require__(7059) +const { kState, kHeaders, kGuard, kRealm } = __nccwpck_require__(8085) +const { webidl } = __nccwpck_require__(1537) +const { FormData } = __nccwpck_require__(968) +const { getGlobalOrigin } = __nccwpck_require__(5799) +const { URLSerializer } = __nccwpck_require__(2791) +const { kHeadersList } = __nccwpck_require__(9440) +const assert = __nccwpck_require__(9491) +const { types } = __nccwpck_require__(3837) + +const ReadableStream = globalThis.ReadableStream || (__nccwpck_require__(5356).ReadableStream) +const textEncoder = new TextEncoder('utf-8') + +// https://fetch.spec.whatwg.org/#response-class +class Response { + // Creates network error Response. + static error () { + // TODO + const relevantRealm = { settingsObject: {} } + + // The static error() method steps are to return the result of creating a + // Response object, given a new network error, "immutable", and this’s + // relevant Realm. + const responseObject = new Response() + responseObject[kState] = makeNetworkError() + responseObject[kRealm] = relevantRealm + responseObject[kHeaders][kHeadersList] = responseObject[kState].headersList + responseObject[kHeaders][kGuard] = 'immutable' + responseObject[kHeaders][kRealm] = relevantRealm + return responseObject + } + + // https://fetch.spec.whatwg.org/#dom-response-json + static json (data, init = {}) { + webidl.argumentLengthCheck(arguments, 1, { header: 'Response.json' }) + + if (init !== null) { + init = webidl.converters.ResponseInit(init) + } + + // 1. Let bytes the result of running serialize a JavaScript value to JSON bytes on data. + const bytes = textEncoder.encode( + serializeJavascriptValueToJSONString(data) + ) + + // 2. Let body be the result of extracting bytes. + const body = extractBody(bytes) + + // 3. Let responseObject be the result of creating a Response object, given a new response, + // "response", and this’s relevant Realm. + const relevantRealm = { settingsObject: {} } + const responseObject = new Response() + responseObject[kRealm] = relevantRealm + responseObject[kHeaders][kGuard] = 'response' + responseObject[kHeaders][kRealm] = relevantRealm + + // 4. Perform initialize a response given responseObject, init, and (body, "application/json"). + initializeResponse(responseObject, init, { body: body[0], type: 'application/json' }) + + // 5. Return responseObject. + return responseObject + } + + // Creates a redirect Response that redirects to url with status status. + static redirect (url, status = 302) { + const relevantRealm = { settingsObject: {} } + + webidl.argumentLengthCheck(arguments, 1, { header: 'Response.redirect' }) + + url = webidl.converters.USVString(url) + status = webidl.converters['unsigned short'](status) + + // 1. Let parsedURL be the result of parsing url with current settings + // object’s API base URL. + // 2. If parsedURL is failure, then throw a TypeError. + // TODO: base-URL? + let parsedURL + try { + parsedURL = new URL(url, getGlobalOrigin()) + } catch (err) { + throw Object.assign(new TypeError('Failed to parse URL from ' + url), { + cause: err + }) + } + + // 3. If status is not a redirect status, then throw a RangeError. + if (!redirectStatusSet.has(status)) { + throw new RangeError('Invalid status code ' + status) + } + + // 4. Let responseObject be the result of creating a Response object, + // given a new response, "immutable", and this’s relevant Realm. + const responseObject = new Response() + responseObject[kRealm] = relevantRealm + responseObject[kHeaders][kGuard] = 'immutable' + responseObject[kHeaders][kRealm] = relevantRealm + + // 5. Set responseObject’s response’s status to status. + responseObject[kState].status = status + + // 6. Let value be parsedURL, serialized and isomorphic encoded. + const value = isomorphicEncode(URLSerializer(parsedURL)) + + // 7. Append `Location`/value to responseObject’s response’s header list. + responseObject[kState].headersList.append('location', value) + + // 8. Return responseObject. + return responseObject + } + + // https://fetch.spec.whatwg.org/#dom-response + constructor (body = null, init = {}) { + if (body !== null) { + body = webidl.converters.BodyInit(body) + } + + init = webidl.converters.ResponseInit(init) + + // TODO + this[kRealm] = { settingsObject: {} } + + // 1. Set this’s response to a new response. + this[kState] = makeResponse({}) + + // 2. Set this’s headers to a new Headers object with this’s relevant + // Realm, whose header list is this’s response’s header list and guard + // is "response". + this[kHeaders] = new Headers() + this[kHeaders][kGuard] = 'response' + this[kHeaders][kHeadersList] = this[kState].headersList + this[kHeaders][kRealm] = this[kRealm] + + // 3. Let bodyWithType be null. + let bodyWithType = null + + // 4. If body is non-null, then set bodyWithType to the result of extracting body. + if (body != null) { + const [extractedBody, type] = extractBody(body) + bodyWithType = { body: extractedBody, type } + } + + // 5. Perform initialize a response given this, init, and bodyWithType. + initializeResponse(this, init, bodyWithType) + } + + // Returns response’s type, e.g., "cors". + get type () { + webidl.brandCheck(this, Response) + + // The type getter steps are to return this’s response’s type. + return this[kState].type + } + + // Returns response’s URL, if it has one; otherwise the empty string. + get url () { + webidl.brandCheck(this, Response) + + const urlList = this[kState].urlList + + // The url getter steps are to return the empty string if this’s + // response’s URL is null; otherwise this’s response’s URL, + // serialized with exclude fragment set to true. + const url = urlList[urlList.length - 1] ?? null + + if (url === null) { + return '' + } + + return URLSerializer(url, true) + } + + // Returns whether response was obtained through a redirect. + get redirected () { + webidl.brandCheck(this, Response) + + // The redirected getter steps are to return true if this’s response’s URL + // list has more than one item; otherwise false. + return this[kState].urlList.length > 1 + } + + // Returns response’s status. + get status () { + webidl.brandCheck(this, Response) + + // The status getter steps are to return this’s response’s status. + return this[kState].status + } + + // Returns whether response’s status is an ok status. + get ok () { + webidl.brandCheck(this, Response) + + // The ok getter steps are to return true if this’s response’s status is an + // ok status; otherwise false. + return this[kState].status >= 200 && this[kState].status <= 299 + } + + // Returns response’s status message. + get statusText () { + webidl.brandCheck(this, Response) + + // The statusText getter steps are to return this’s response’s status + // message. + return this[kState].statusText + } + + // Returns response’s headers as Headers. + get headers () { + webidl.brandCheck(this, Response) + + // The headers getter steps are to return this’s headers. + return this[kHeaders] + } + + get body () { + webidl.brandCheck(this, Response) + + return this[kState].body ? this[kState].body.stream : null + } + + get bodyUsed () { + webidl.brandCheck(this, Response) + + return !!this[kState].body && util.isDisturbed(this[kState].body.stream) + } + + // Returns a clone of response. + clone () { + webidl.brandCheck(this, Response) + + // 1. If this is unusable, then throw a TypeError. + if (this.bodyUsed || (this.body && this.body.locked)) { + throw webidl.errors.exception({ + header: 'Response.clone', + message: 'Body has already been consumed.' + }) + } + + // 2. Let clonedResponse be the result of cloning this’s response. + const clonedResponse = cloneResponse(this[kState]) + + // 3. Return the result of creating a Response object, given + // clonedResponse, this’s headers’s guard, and this’s relevant Realm. + const clonedResponseObject = new Response() + clonedResponseObject[kState] = clonedResponse + clonedResponseObject[kRealm] = this[kRealm] + clonedResponseObject[kHeaders][kHeadersList] = clonedResponse.headersList + clonedResponseObject[kHeaders][kGuard] = this[kHeaders][kGuard] + clonedResponseObject[kHeaders][kRealm] = this[kHeaders][kRealm] + + return clonedResponseObject + } +} + +mixinBody(Response) + +Object.defineProperties(Response.prototype, { + type: kEnumerableProperty, + url: kEnumerableProperty, + status: kEnumerableProperty, + ok: kEnumerableProperty, + redirected: kEnumerableProperty, + statusText: kEnumerableProperty, + headers: kEnumerableProperty, + clone: kEnumerableProperty, + body: kEnumerableProperty, + bodyUsed: kEnumerableProperty, + [Symbol.toStringTag]: { + value: 'Response', + configurable: true + } +}) + +Object.defineProperties(Response, { + json: kEnumerableProperty, + redirect: kEnumerableProperty, + error: kEnumerableProperty +}) + +// https://fetch.spec.whatwg.org/#concept-response-clone +function cloneResponse (response) { + // To clone a response response, run these steps: + + // 1. If response is a filtered response, then return a new identical + // filtered response whose internal response is a clone of response’s + // internal response. + if (response.internalResponse) { + return filterResponse( + cloneResponse(response.internalResponse), + response.type + ) + } + + // 2. Let newResponse be a copy of response, except for its body. + const newResponse = makeResponse({ ...response, body: null }) + + // 3. If response’s body is non-null, then set newResponse’s body to the + // result of cloning response’s body. + if (response.body != null) { + newResponse.body = cloneBody(response.body) + } + + // 4. Return newResponse. + return newResponse +} + +function makeResponse (init) { + return { + aborted: false, + rangeRequested: false, + timingAllowPassed: false, + requestIncludesCredentials: false, + type: 'default', + status: 200, + timingInfo: null, + cacheState: '', + statusText: '', + ...init, + headersList: init.headersList + ? new HeadersList(init.headersList) + : new HeadersList(), + urlList: init.urlList ? [...init.urlList] : [] + } +} + +function makeNetworkError (reason) { + const isError = isErrorLike(reason) + return makeResponse({ + type: 'error', + status: 0, + error: isError + ? reason + : new Error(reason ? String(reason) : reason), + aborted: reason && reason.name === 'AbortError' + }) +} + +function makeFilteredResponse (response, state) { + state = { + internalResponse: response, + ...state + } + + return new Proxy(response, { + get (target, p) { + return p in state ? state[p] : target[p] + }, + set (target, p, value) { + assert(!(p in state)) + target[p] = value + return true + } + }) +} + +// https://fetch.spec.whatwg.org/#concept-filtered-response +function filterResponse (response, type) { + // Set response to the following filtered response with response as its + // internal response, depending on request’s response tainting: + if (type === 'basic') { + // A basic filtered response is a filtered response whose type is "basic" + // and header list excludes any headers in internal response’s header list + // whose name is a forbidden response-header name. + + // Note: undici does not implement forbidden response-header names + return makeFilteredResponse(response, { + type: 'basic', + headersList: response.headersList + }) + } else if (type === 'cors') { + // A CORS filtered response is a filtered response whose type is "cors" + // and header list excludes any headers in internal response’s header + // list whose name is not a CORS-safelisted response-header name, given + // internal response’s CORS-exposed header-name list. + + // Note: undici does not implement CORS-safelisted response-header names + return makeFilteredResponse(response, { + type: 'cors', + headersList: response.headersList + }) + } else if (type === 'opaque') { + // An opaque filtered response is a filtered response whose type is + // "opaque", URL list is the empty list, status is 0, status message + // is the empty byte sequence, header list is empty, and body is null. + + return makeFilteredResponse(response, { + type: 'opaque', + urlList: Object.freeze([]), + status: 0, + statusText: '', + body: null + }) + } else if (type === 'opaqueredirect') { + // An opaque-redirect filtered response is a filtered response whose type + // is "opaqueredirect", status is 0, status message is the empty byte + // sequence, header list is empty, and body is null. + + return makeFilteredResponse(response, { + type: 'opaqueredirect', + status: 0, + statusText: '', + headersList: [], + body: null + }) + } else { + assert(false) + } +} + +// https://fetch.spec.whatwg.org/#appropriate-network-error +function makeAppropriateNetworkError (fetchParams, err = null) { + // 1. Assert: fetchParams is canceled. + assert(isCancelled(fetchParams)) + + // 2. Return an aborted network error if fetchParams is aborted; + // otherwise return a network error. + return isAborted(fetchParams) + ? makeNetworkError(Object.assign(new DOMException('The operation was aborted.', 'AbortError'), { cause: err })) + : makeNetworkError(Object.assign(new DOMException('Request was cancelled.'), { cause: err })) +} + +// https://whatpr.org/fetch/1392.html#initialize-a-response +function initializeResponse (response, init, body) { + // 1. If init["status"] is not in the range 200 to 599, inclusive, then + // throw a RangeError. + if (init.status !== null && (init.status < 200 || init.status > 599)) { + throw new RangeError('init["status"] must be in the range of 200 to 599, inclusive.') + } + + // 2. If init["statusText"] does not match the reason-phrase token production, + // then throw a TypeError. + if ('statusText' in init && init.statusText != null) { + // See, https://datatracker.ietf.org/doc/html/rfc7230#section-3.1.2: + // reason-phrase = *( HTAB / SP / VCHAR / obs-text ) + if (!isValidReasonPhrase(String(init.statusText))) { + throw new TypeError('Invalid statusText') + } + } + + // 3. Set response’s response’s status to init["status"]. + if ('status' in init && init.status != null) { + response[kState].status = init.status + } + + // 4. Set response’s response’s status message to init["statusText"]. + if ('statusText' in init && init.statusText != null) { + response[kState].statusText = init.statusText + } + + // 5. If init["headers"] exists, then fill response’s headers with init["headers"]. + if ('headers' in init && init.headers != null) { + fill(response[kHeaders], init.headers) + } + + // 6. If body was given, then: + if (body) { + // 1. If response's status is a null body status, then throw a TypeError. + if (nullBodyStatus.includes(response.status)) { + throw webidl.errors.exception({ + header: 'Response constructor', + message: 'Invalid response status code ' + response.status + }) + } + + // 2. Set response's body to body's body. + response[kState].body = body.body + + // 3. If body's type is non-null and response's header list does not contain + // `Content-Type`, then append (`Content-Type`, body's type) to response's header list. + if (body.type != null && !response[kState].headersList.contains('Content-Type')) { + response[kState].headersList.append('content-type', body.type) + } + } +} + +webidl.converters.ReadableStream = webidl.interfaceConverter( + ReadableStream +) + +webidl.converters.FormData = webidl.interfaceConverter( + FormData +) + +webidl.converters.URLSearchParams = webidl.interfaceConverter( + URLSearchParams +) + +// https://fetch.spec.whatwg.org/#typedefdef-xmlhttprequestbodyinit +webidl.converters.XMLHttpRequestBodyInit = function (V) { + if (typeof V === 'string') { + return webidl.converters.USVString(V) + } + + if (isBlobLike(V)) { + return webidl.converters.Blob(V, { strict: false }) + } + + if ( + types.isAnyArrayBuffer(V) || + types.isTypedArray(V) || + types.isDataView(V) + ) { + return webidl.converters.BufferSource(V) + } + + if (util.isFormDataLike(V)) { + return webidl.converters.FormData(V, { strict: false }) + } + + if (V instanceof URLSearchParams) { + return webidl.converters.URLSearchParams(V) + } + + return webidl.converters.DOMString(V) +} + +// https://fetch.spec.whatwg.org/#bodyinit +webidl.converters.BodyInit = function (V) { + if (V instanceof ReadableStream) { + return webidl.converters.ReadableStream(V) + } + + // Note: the spec doesn't include async iterables, + // this is an undici extension. + if (V?.[Symbol.asyncIterator]) { + return V + } + + return webidl.converters.XMLHttpRequestBodyInit(V) +} + +webidl.converters.ResponseInit = webidl.dictionaryConverter([ + { + key: 'status', + converter: webidl.converters['unsigned short'], + defaultValue: 200 + }, + { + key: 'statusText', + converter: webidl.converters.ByteString, + defaultValue: '' + }, + { + key: 'headers', + converter: webidl.converters.HeadersInit + } +]) + +module.exports = { + makeNetworkError, + makeResponse, + makeAppropriateNetworkError, + filterResponse, + Response, + cloneResponse +} + + +/***/ }), + +/***/ 8085: +/***/ ((module) => { + +"use strict"; + + +module.exports = { + kUrl: Symbol('url'), + kHeaders: Symbol('headers'), + kSignal: Symbol('signal'), + kState: Symbol('state'), + kGuard: Symbol('guard'), + kRealm: Symbol('realm') +} + + +/***/ }), + +/***/ 784: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { redirectStatusSet, referrerPolicySet: referrerPolicyTokens, badPortsSet } = __nccwpck_require__(7059) +const { getGlobalOrigin } = __nccwpck_require__(5799) +const { performance } = __nccwpck_require__(4074) +const { isBlobLike, toUSVString, ReadableStreamFrom } = __nccwpck_require__(9522) +const assert = __nccwpck_require__(9491) +const { isUint8Array } = __nccwpck_require__(9830) + +// https://nodejs.org/api/crypto.html#determining-if-crypto-support-is-unavailable +/** @type {import('crypto')|undefined} */ +let crypto + +try { + crypto = __nccwpck_require__(6113) +} catch { + +} + +function responseURL (response) { + // https://fetch.spec.whatwg.org/#responses + // A response has an associated URL. It is a pointer to the last URL + // in response’s URL list and null if response’s URL list is empty. + const urlList = response.urlList + const length = urlList.length + return length === 0 ? null : urlList[length - 1].toString() +} + +// https://fetch.spec.whatwg.org/#concept-response-location-url +function responseLocationURL (response, requestFragment) { + // 1. If response’s status is not a redirect status, then return null. + if (!redirectStatusSet.has(response.status)) { + return null + } + + // 2. Let location be the result of extracting header list values given + // `Location` and response’s header list. + let location = response.headersList.get('location') + + // 3. If location is a header value, then set location to the result of + // parsing location with response’s URL. + if (location !== null && isValidHeaderValue(location)) { + location = new URL(location, responseURL(response)) + } + + // 4. If location is a URL whose fragment is null, then set location’s + // fragment to requestFragment. + if (location && !location.hash) { + location.hash = requestFragment + } + + // 5. Return location. + return location +} + +/** @returns {URL} */ +function requestCurrentURL (request) { + return request.urlList[request.urlList.length - 1] +} + +function requestBadPort (request) { + // 1. Let url be request’s current URL. + const url = requestCurrentURL(request) + + // 2. If url’s scheme is an HTTP(S) scheme and url’s port is a bad port, + // then return blocked. + if (urlIsHttpHttpsScheme(url) && badPortsSet.has(url.port)) { + return 'blocked' + } + + // 3. Return allowed. + return 'allowed' +} + +function isErrorLike (object) { + return object instanceof Error || ( + object?.constructor?.name === 'Error' || + object?.constructor?.name === 'DOMException' + ) +} + +// Check whether |statusText| is a ByteString and +// matches the Reason-Phrase token production. +// RFC 2616: https://tools.ietf.org/html/rfc2616 +// RFC 7230: https://tools.ietf.org/html/rfc7230 +// "reason-phrase = *( HTAB / SP / VCHAR / obs-text )" +// https://github.com/chromium/chromium/blob/94.0.4604.1/third_party/blink/renderer/core/fetch/response.cc#L116 +function isValidReasonPhrase (statusText) { + for (let i = 0; i < statusText.length; ++i) { + const c = statusText.charCodeAt(i) + if ( + !( + ( + c === 0x09 || // HTAB + (c >= 0x20 && c <= 0x7e) || // SP / VCHAR + (c >= 0x80 && c <= 0xff) + ) // obs-text + ) + ) { + return false + } + } + return true +} + +/** + * @see https://tools.ietf.org/html/rfc7230#section-3.2.6 + * @param {number} c + */ +function isTokenCharCode (c) { + switch (c) { + case 0x22: + case 0x28: + case 0x29: + case 0x2c: + case 0x2f: + case 0x3a: + case 0x3b: + case 0x3c: + case 0x3d: + case 0x3e: + case 0x3f: + case 0x40: + case 0x5b: + case 0x5c: + case 0x5d: + case 0x7b: + case 0x7d: + // DQUOTE and "(),/:;<=>?@[\]{}" + return false + default: + // VCHAR %x21-7E + return c >= 0x21 && c <= 0x7e + } +} + +/** + * @param {string} characters + */ +function isValidHTTPToken (characters) { + if (characters.length === 0) { + return false + } + for (let i = 0; i < characters.length; ++i) { + if (!isTokenCharCode(characters.charCodeAt(i))) { + return false + } + } + return true +} + +/** + * @see https://fetch.spec.whatwg.org/#header-name + * @param {string} potentialValue + */ +function isValidHeaderName (potentialValue) { + return isValidHTTPToken(potentialValue) +} + +/** + * @see https://fetch.spec.whatwg.org/#header-value + * @param {string} potentialValue + */ +function isValidHeaderValue (potentialValue) { + // - Has no leading or trailing HTTP tab or space bytes. + // - Contains no 0x00 (NUL) or HTTP newline bytes. + if ( + potentialValue.startsWith('\t') || + potentialValue.startsWith(' ') || + potentialValue.endsWith('\t') || + potentialValue.endsWith(' ') + ) { + return false + } + + if ( + potentialValue.includes('\0') || + potentialValue.includes('\r') || + potentialValue.includes('\n') + ) { + return false + } + + return true +} + +// https://w3c.github.io/webappsec-referrer-policy/#set-requests-referrer-policy-on-redirect +function setRequestReferrerPolicyOnRedirect (request, actualResponse) { + // Given a request request and a response actualResponse, this algorithm + // updates request’s referrer policy according to the Referrer-Policy + // header (if any) in actualResponse. + + // 1. Let policy be the result of executing § 8.1 Parse a referrer policy + // from a Referrer-Policy header on actualResponse. + + // 8.1 Parse a referrer policy from a Referrer-Policy header + // 1. Let policy-tokens be the result of extracting header list values given `Referrer-Policy` and response’s header list. + const { headersList } = actualResponse + // 2. Let policy be the empty string. + // 3. For each token in policy-tokens, if token is a referrer policy and token is not the empty string, then set policy to token. + // 4. Return policy. + const policyHeader = (headersList.get('referrer-policy') ?? '').split(',') + + // Note: As the referrer-policy can contain multiple policies + // separated by comma, we need to loop through all of them + // and pick the first valid one. + // Ref: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy#specify_a_fallback_policy + let policy = '' + if (policyHeader.length > 0) { + // The right-most policy takes precedence. + // The left-most policy is the fallback. + for (let i = policyHeader.length; i !== 0; i--) { + const token = policyHeader[i - 1].trim() + if (referrerPolicyTokens.has(token)) { + policy = token + break + } + } + } + + // 2. If policy is not the empty string, then set request’s referrer policy to policy. + if (policy !== '') { + request.referrerPolicy = policy + } +} + +// https://fetch.spec.whatwg.org/#cross-origin-resource-policy-check +function crossOriginResourcePolicyCheck () { + // TODO + return 'allowed' +} + +// https://fetch.spec.whatwg.org/#concept-cors-check +function corsCheck () { + // TODO + return 'success' +} + +// https://fetch.spec.whatwg.org/#concept-tao-check +function TAOCheck () { + // TODO + return 'success' +} + +function appendFetchMetadata (httpRequest) { + // https://w3c.github.io/webappsec-fetch-metadata/#sec-fetch-dest-header + // TODO + + // https://w3c.github.io/webappsec-fetch-metadata/#sec-fetch-mode-header + + // 1. Assert: r’s url is a potentially trustworthy URL. + // TODO + + // 2. Let header be a Structured Header whose value is a token. + let header = null + + // 3. Set header’s value to r’s mode. + header = httpRequest.mode + + // 4. Set a structured field value `Sec-Fetch-Mode`/header in r’s header list. + httpRequest.headersList.set('sec-fetch-mode', header) + + // https://w3c.github.io/webappsec-fetch-metadata/#sec-fetch-site-header + // TODO + + // https://w3c.github.io/webappsec-fetch-metadata/#sec-fetch-user-header + // TODO +} + +// https://fetch.spec.whatwg.org/#append-a-request-origin-header +function appendRequestOriginHeader (request) { + // 1. Let serializedOrigin be the result of byte-serializing a request origin with request. + let serializedOrigin = request.origin + + // 2. If request’s response tainting is "cors" or request’s mode is "websocket", then append (`Origin`, serializedOrigin) to request’s header list. + if (request.responseTainting === 'cors' || request.mode === 'websocket') { + if (serializedOrigin) { + request.headersList.append('origin', serializedOrigin) + } + + // 3. Otherwise, if request’s method is neither `GET` nor `HEAD`, then: + } else if (request.method !== 'GET' && request.method !== 'HEAD') { + // 1. Switch on request’s referrer policy: + switch (request.referrerPolicy) { + case 'no-referrer': + // Set serializedOrigin to `null`. + serializedOrigin = null + break + case 'no-referrer-when-downgrade': + case 'strict-origin': + case 'strict-origin-when-cross-origin': + // If request’s origin is a tuple origin, its scheme is "https", and request’s current URL’s scheme is not "https", then set serializedOrigin to `null`. + if (request.origin && urlHasHttpsScheme(request.origin) && !urlHasHttpsScheme(requestCurrentURL(request))) { + serializedOrigin = null + } + break + case 'same-origin': + // If request’s origin is not same origin with request’s current URL’s origin, then set serializedOrigin to `null`. + if (!sameOrigin(request, requestCurrentURL(request))) { + serializedOrigin = null + } + break + default: + // Do nothing. + } + + if (serializedOrigin) { + // 2. Append (`Origin`, serializedOrigin) to request’s header list. + request.headersList.append('origin', serializedOrigin) + } + } +} + +function coarsenedSharedCurrentTime (crossOriginIsolatedCapability) { + // TODO + return performance.now() +} + +// https://fetch.spec.whatwg.org/#create-an-opaque-timing-info +function createOpaqueTimingInfo (timingInfo) { + return { + startTime: timingInfo.startTime ?? 0, + redirectStartTime: 0, + redirectEndTime: 0, + postRedirectStartTime: timingInfo.startTime ?? 0, + finalServiceWorkerStartTime: 0, + finalNetworkResponseStartTime: 0, + finalNetworkRequestStartTime: 0, + endTime: 0, + encodedBodySize: 0, + decodedBodySize: 0, + finalConnectionTimingInfo: null + } +} + +// https://html.spec.whatwg.org/multipage/origin.html#policy-container +function makePolicyContainer () { + // Note: the fetch spec doesn't make use of embedder policy or CSP list + return { + referrerPolicy: 'strict-origin-when-cross-origin' + } +} + +// https://html.spec.whatwg.org/multipage/origin.html#clone-a-policy-container +function clonePolicyContainer (policyContainer) { + return { + referrerPolicy: policyContainer.referrerPolicy + } +} + +// https://w3c.github.io/webappsec-referrer-policy/#determine-requests-referrer +function determineRequestsReferrer (request) { + // 1. Let policy be request's referrer policy. + const policy = request.referrerPolicy + + // Note: policy cannot (shouldn't) be null or an empty string. + assert(policy) + + // 2. Let environment be request’s client. + + let referrerSource = null + + // 3. Switch on request’s referrer: + if (request.referrer === 'client') { + // Note: node isn't a browser and doesn't implement document/iframes, + // so we bypass this step and replace it with our own. + + const globalOrigin = getGlobalOrigin() + + if (!globalOrigin || globalOrigin.origin === 'null') { + return 'no-referrer' + } + + // note: we need to clone it as it's mutated + referrerSource = new URL(globalOrigin) + } else if (request.referrer instanceof URL) { + // Let referrerSource be request’s referrer. + referrerSource = request.referrer + } + + // 4. Let request’s referrerURL be the result of stripping referrerSource for + // use as a referrer. + let referrerURL = stripURLForReferrer(referrerSource) + + // 5. Let referrerOrigin be the result of stripping referrerSource for use as + // a referrer, with the origin-only flag set to true. + const referrerOrigin = stripURLForReferrer(referrerSource, true) + + // 6. If the result of serializing referrerURL is a string whose length is + // greater than 4096, set referrerURL to referrerOrigin. + if (referrerURL.toString().length > 4096) { + referrerURL = referrerOrigin + } + + const areSameOrigin = sameOrigin(request, referrerURL) + const isNonPotentiallyTrustWorthy = isURLPotentiallyTrustworthy(referrerURL) && + !isURLPotentiallyTrustworthy(request.url) + + // 8. Execute the switch statements corresponding to the value of policy: + switch (policy) { + case 'origin': return referrerOrigin != null ? referrerOrigin : stripURLForReferrer(referrerSource, true) + case 'unsafe-url': return referrerURL + case 'same-origin': + return areSameOrigin ? referrerOrigin : 'no-referrer' + case 'origin-when-cross-origin': + return areSameOrigin ? referrerURL : referrerOrigin + case 'strict-origin-when-cross-origin': { + const currentURL = requestCurrentURL(request) + + // 1. If the origin of referrerURL and the origin of request’s current + // URL are the same, then return referrerURL. + if (sameOrigin(referrerURL, currentURL)) { + return referrerURL + } + + // 2. If referrerURL is a potentially trustworthy URL and request’s + // current URL is not a potentially trustworthy URL, then return no + // referrer. + if (isURLPotentiallyTrustworthy(referrerURL) && !isURLPotentiallyTrustworthy(currentURL)) { + return 'no-referrer' + } + + // 3. Return referrerOrigin. + return referrerOrigin + } + case 'strict-origin': // eslint-disable-line + /** + * 1. If referrerURL is a potentially trustworthy URL and + * request’s current URL is not a potentially trustworthy URL, + * then return no referrer. + * 2. Return referrerOrigin + */ + case 'no-referrer-when-downgrade': // eslint-disable-line + /** + * 1. If referrerURL is a potentially trustworthy URL and + * request’s current URL is not a potentially trustworthy URL, + * then return no referrer. + * 2. Return referrerOrigin + */ + + default: // eslint-disable-line + return isNonPotentiallyTrustWorthy ? 'no-referrer' : referrerOrigin + } +} + +/** + * @see https://w3c.github.io/webappsec-referrer-policy/#strip-url + * @param {URL} url + * @param {boolean|undefined} originOnly + */ +function stripURLForReferrer (url, originOnly) { + // 1. Assert: url is a URL. + assert(url instanceof URL) + + // 2. If url’s scheme is a local scheme, then return no referrer. + if (url.protocol === 'file:' || url.protocol === 'about:' || url.protocol === 'blank:') { + return 'no-referrer' + } + + // 3. Set url’s username to the empty string. + url.username = '' + + // 4. Set url’s password to the empty string. + url.password = '' + + // 5. Set url’s fragment to null. + url.hash = '' + + // 6. If the origin-only flag is true, then: + if (originOnly) { + // 1. Set url’s path to « the empty string ». + url.pathname = '' + + // 2. Set url’s query to null. + url.search = '' + } + + // 7. Return url. + return url +} + +function isURLPotentiallyTrustworthy (url) { + if (!(url instanceof URL)) { + return false + } + + // If child of about, return true + if (url.href === 'about:blank' || url.href === 'about:srcdoc') { + return true + } + + // If scheme is data, return true + if (url.protocol === 'data:') return true + + // If file, return true + if (url.protocol === 'file:') return true + + return isOriginPotentiallyTrustworthy(url.origin) + + function isOriginPotentiallyTrustworthy (origin) { + // If origin is explicitly null, return false + if (origin == null || origin === 'null') return false + + const originAsURL = new URL(origin) + + // If secure, return true + if (originAsURL.protocol === 'https:' || originAsURL.protocol === 'wss:') { + return true + } + + // If localhost or variants, return true + if (/^127(?:\.[0-9]+){0,2}\.[0-9]+$|^\[(?:0*:)*?:?0*1\]$/.test(originAsURL.hostname) || + (originAsURL.hostname === 'localhost' || originAsURL.hostname.includes('localhost.')) || + (originAsURL.hostname.endsWith('.localhost'))) { + return true + } + + // If any other, return false + return false + } +} + +/** + * @see https://w3c.github.io/webappsec-subresource-integrity/#does-response-match-metadatalist + * @param {Uint8Array} bytes + * @param {string} metadataList + */ +function bytesMatch (bytes, metadataList) { + // If node is not built with OpenSSL support, we cannot check + // a request's integrity, so allow it by default (the spec will + // allow requests if an invalid hash is given, as precedence). + /* istanbul ignore if: only if node is built with --without-ssl */ + if (crypto === undefined) { + return true + } + + // 1. Let parsedMetadata be the result of parsing metadataList. + const parsedMetadata = parseMetadata(metadataList) + + // 2. If parsedMetadata is no metadata, return true. + if (parsedMetadata === 'no metadata') { + return true + } + + // 3. If parsedMetadata is the empty set, return true. + if (parsedMetadata.length === 0) { + return true + } + + // 4. Let metadata be the result of getting the strongest + // metadata from parsedMetadata. + const list = parsedMetadata.sort((c, d) => d.algo.localeCompare(c.algo)) + // get the strongest algorithm + const strongest = list[0].algo + // get all entries that use the strongest algorithm; ignore weaker + const metadata = list.filter((item) => item.algo === strongest) + + // 5. For each item in metadata: + for (const item of metadata) { + // 1. Let algorithm be the alg component of item. + const algorithm = item.algo + + // 2. Let expectedValue be the val component of item. + let expectedValue = item.hash + + // See https://github.com/web-platform-tests/wpt/commit/e4c5cc7a5e48093220528dfdd1c4012dc3837a0e + // "be liberal with padding". This is annoying, and it's not even in the spec. + + if (expectedValue.endsWith('==')) { + expectedValue = expectedValue.slice(0, -2) + } + + // 3. Let actualValue be the result of applying algorithm to bytes. + let actualValue = crypto.createHash(algorithm).update(bytes).digest('base64') + + if (actualValue.endsWith('==')) { + actualValue = actualValue.slice(0, -2) + } + + // 4. If actualValue is a case-sensitive match for expectedValue, + // return true. + if (actualValue === expectedValue) { + return true + } + + let actualBase64URL = crypto.createHash(algorithm).update(bytes).digest('base64url') + + if (actualBase64URL.endsWith('==')) { + actualBase64URL = actualBase64URL.slice(0, -2) + } + + if (actualBase64URL === expectedValue) { + return true + } + } + + // 6. Return false. + return false +} + +// https://w3c.github.io/webappsec-subresource-integrity/#grammardef-hash-with-options +// https://www.w3.org/TR/CSP2/#source-list-syntax +// https://www.rfc-editor.org/rfc/rfc5234#appendix-B.1 +const parseHashWithOptions = /((?sha256|sha384|sha512)-(?[A-z0-9+/]{1}.*={0,2}))( +[\x21-\x7e]?)?/i + +/** + * @see https://w3c.github.io/webappsec-subresource-integrity/#parse-metadata + * @param {string} metadata + */ +function parseMetadata (metadata) { + // 1. Let result be the empty set. + /** @type {{ algo: string, hash: string }[]} */ + const result = [] + + // 2. Let empty be equal to true. + let empty = true + + const supportedHashes = crypto.getHashes() + + // 3. For each token returned by splitting metadata on spaces: + for (const token of metadata.split(' ')) { + // 1. Set empty to false. + empty = false + + // 2. Parse token as a hash-with-options. + const parsedToken = parseHashWithOptions.exec(token) + + // 3. If token does not parse, continue to the next token. + if (parsedToken === null || parsedToken.groups === undefined) { + // Note: Chromium blocks the request at this point, but Firefox + // gives a warning that an invalid integrity was given. The + // correct behavior is to ignore these, and subsequently not + // check the integrity of the resource. + continue + } + + // 4. Let algorithm be the hash-algo component of token. + const algorithm = parsedToken.groups.algo + + // 5. If algorithm is a hash function recognized by the user + // agent, add the parsed token to result. + if (supportedHashes.includes(algorithm.toLowerCase())) { + result.push(parsedToken.groups) + } + } + + // 4. Return no metadata if empty is true, otherwise return result. + if (empty === true) { + return 'no metadata' + } + + return result +} + +// https://w3c.github.io/webappsec-upgrade-insecure-requests/#upgrade-request +function tryUpgradeRequestToAPotentiallyTrustworthyURL (request) { + // TODO +} + +/** + * @link {https://html.spec.whatwg.org/multipage/origin.html#same-origin} + * @param {URL} A + * @param {URL} B + */ +function sameOrigin (A, B) { + // 1. If A and B are the same opaque origin, then return true. + if (A.origin === B.origin && A.origin === 'null') { + return true + } + + // 2. If A and B are both tuple origins and their schemes, + // hosts, and port are identical, then return true. + if (A.protocol === B.protocol && A.hostname === B.hostname && A.port === B.port) { + return true + } + + // 3. Return false. + return false +} + +function createDeferredPromise () { + let res + let rej + const promise = new Promise((resolve, reject) => { + res = resolve + rej = reject + }) + + return { promise, resolve: res, reject: rej } +} + +function isAborted (fetchParams) { + return fetchParams.controller.state === 'aborted' +} + +function isCancelled (fetchParams) { + return fetchParams.controller.state === 'aborted' || + fetchParams.controller.state === 'terminated' +} + +const normalizeMethodRecord = { + delete: 'DELETE', + DELETE: 'DELETE', + get: 'GET', + GET: 'GET', + head: 'HEAD', + HEAD: 'HEAD', + options: 'OPTIONS', + OPTIONS: 'OPTIONS', + post: 'POST', + POST: 'POST', + put: 'PUT', + PUT: 'PUT' +} + +// Note: object prototypes should not be able to be referenced. e.g. `Object#hasOwnProperty`. +Object.setPrototypeOf(normalizeMethodRecord, null) + +/** + * @see https://fetch.spec.whatwg.org/#concept-method-normalize + * @param {string} method + */ +function normalizeMethod (method) { + return normalizeMethodRecord[method.toLowerCase()] ?? method +} + +// https://infra.spec.whatwg.org/#serialize-a-javascript-value-to-a-json-string +function serializeJavascriptValueToJSONString (value) { + // 1. Let result be ? Call(%JSON.stringify%, undefined, « value »). + const result = JSON.stringify(value) + + // 2. If result is undefined, then throw a TypeError. + if (result === undefined) { + throw new TypeError('Value is not JSON serializable') + } + + // 3. Assert: result is a string. + assert(typeof result === 'string') + + // 4. Return result. + return result +} + +// https://tc39.es/ecma262/#sec-%25iteratorprototype%25-object +const esIteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]())) + +/** + * @see https://webidl.spec.whatwg.org/#dfn-iterator-prototype-object + * @param {() => unknown[]} iterator + * @param {string} name name of the instance + * @param {'key'|'value'|'key+value'} kind + */ +function makeIterator (iterator, name, kind) { + const object = { + index: 0, + kind, + target: iterator + } + + const i = { + next () { + // 1. Let interface be the interface for which the iterator prototype object exists. + + // 2. Let thisValue be the this value. + + // 3. Let object be ? ToObject(thisValue). + + // 4. If object is a platform object, then perform a security + // check, passing: + + // 5. If object is not a default iterator object for interface, + // then throw a TypeError. + if (Object.getPrototypeOf(this) !== i) { + throw new TypeError( + `'next' called on an object that does not implement interface ${name} Iterator.` + ) + } + + // 6. Let index be object’s index. + // 7. Let kind be object’s kind. + // 8. Let values be object’s target's value pairs to iterate over. + const { index, kind, target } = object + const values = target() + + // 9. Let len be the length of values. + const len = values.length + + // 10. If index is greater than or equal to len, then return + // CreateIterResultObject(undefined, true). + if (index >= len) { + return { value: undefined, done: true } + } + + // 11. Let pair be the entry in values at index index. + const pair = values[index] + + // 12. Set object’s index to index + 1. + object.index = index + 1 + + // 13. Return the iterator result for pair and kind. + return iteratorResult(pair, kind) + }, + // The class string of an iterator prototype object for a given interface is the + // result of concatenating the identifier of the interface and the string " Iterator". + [Symbol.toStringTag]: `${name} Iterator` + } + + // The [[Prototype]] internal slot of an iterator prototype object must be %IteratorPrototype%. + Object.setPrototypeOf(i, esIteratorPrototype) + // esIteratorPrototype needs to be the prototype of i + // which is the prototype of an empty object. Yes, it's confusing. + return Object.setPrototypeOf({}, i) +} + +// https://webidl.spec.whatwg.org/#iterator-result +function iteratorResult (pair, kind) { + let result + + // 1. Let result be a value determined by the value of kind: + switch (kind) { + case 'key': { + // 1. Let idlKey be pair’s key. + // 2. Let key be the result of converting idlKey to an + // ECMAScript value. + // 3. result is key. + result = pair[0] + break + } + case 'value': { + // 1. Let idlValue be pair’s value. + // 2. Let value be the result of converting idlValue to + // an ECMAScript value. + // 3. result is value. + result = pair[1] + break + } + case 'key+value': { + // 1. Let idlKey be pair’s key. + // 2. Let idlValue be pair’s value. + // 3. Let key be the result of converting idlKey to an + // ECMAScript value. + // 4. Let value be the result of converting idlValue to + // an ECMAScript value. + // 5. Let array be ! ArrayCreate(2). + // 6. Call ! CreateDataProperty(array, "0", key). + // 7. Call ! CreateDataProperty(array, "1", value). + // 8. result is array. + result = pair + break + } + } + + // 2. Return CreateIterResultObject(result, false). + return { value: result, done: false } +} + +/** + * @see https://fetch.spec.whatwg.org/#body-fully-read + */ +async function fullyReadBody (body, processBody, processBodyError) { + // 1. If taskDestination is null, then set taskDestination to + // the result of starting a new parallel queue. + + // 2. Let successSteps given a byte sequence bytes be to queue a + // fetch task to run processBody given bytes, with taskDestination. + const successSteps = processBody + + // 3. Let errorSteps be to queue a fetch task to run processBodyError, + // with taskDestination. + const errorSteps = processBodyError + + // 4. Let reader be the result of getting a reader for body’s stream. + // If that threw an exception, then run errorSteps with that + // exception and return. + let reader + + try { + reader = body.stream.getReader() + } catch (e) { + errorSteps(e) + return + } + + // 5. Read all bytes from reader, given successSteps and errorSteps. + try { + const result = await readAllBytes(reader) + successSteps(result) + } catch (e) { + errorSteps(e) + } +} + +/** @type {ReadableStream} */ +let ReadableStream = globalThis.ReadableStream + +function isReadableStreamLike (stream) { + if (!ReadableStream) { + ReadableStream = (__nccwpck_require__(5356).ReadableStream) + } + + return stream instanceof ReadableStream || ( + stream[Symbol.toStringTag] === 'ReadableStream' && + typeof stream.tee === 'function' + ) +} + +const MAXIMUM_ARGUMENT_LENGTH = 65535 + +/** + * @see https://infra.spec.whatwg.org/#isomorphic-decode + * @param {number[]|Uint8Array} input + */ +function isomorphicDecode (input) { + // 1. To isomorphic decode a byte sequence input, return a string whose code point + // length is equal to input’s length and whose code points have the same values + // as the values of input’s bytes, in the same order. + + if (input.length < MAXIMUM_ARGUMENT_LENGTH) { + return String.fromCharCode(...input) + } + + return input.reduce((previous, current) => previous + String.fromCharCode(current), '') +} + +/** + * @param {ReadableStreamController} controller + */ +function readableStreamClose (controller) { + try { + controller.close() + } catch (err) { + // TODO: add comment explaining why this error occurs. + if (!err.message.includes('Controller is already closed')) { + throw err + } + } +} + +/** + * @see https://infra.spec.whatwg.org/#isomorphic-encode + * @param {string} input + */ +function isomorphicEncode (input) { + // 1. Assert: input contains no code points greater than U+00FF. + for (let i = 0; i < input.length; i++) { + assert(input.charCodeAt(i) <= 0xFF) + } + + // 2. Return a byte sequence whose length is equal to input’s code + // point length and whose bytes have the same values as the + // values of input’s code points, in the same order + return input +} + +/** + * @see https://streams.spec.whatwg.org/#readablestreamdefaultreader-read-all-bytes + * @see https://streams.spec.whatwg.org/#read-loop + * @param {ReadableStreamDefaultReader} reader + */ +async function readAllBytes (reader) { + const bytes = [] + let byteLength = 0 + + while (true) { + const { done, value: chunk } = await reader.read() + + if (done) { + // 1. Call successSteps with bytes. + return Buffer.concat(bytes, byteLength) + } + + // 1. If chunk is not a Uint8Array object, call failureSteps + // with a TypeError and abort these steps. + if (!isUint8Array(chunk)) { + throw new TypeError('Received non-Uint8Array chunk') + } + + // 2. Append the bytes represented by chunk to bytes. + bytes.push(chunk) + byteLength += chunk.length + + // 3. Read-loop given reader, bytes, successSteps, and failureSteps. + } +} + +/** + * @see https://fetch.spec.whatwg.org/#is-local + * @param {URL} url + */ +function urlIsLocal (url) { + assert('protocol' in url) // ensure it's a url object + + const protocol = url.protocol + + return protocol === 'about:' || protocol === 'blob:' || protocol === 'data:' +} + +/** + * @param {string|URL} url + */ +function urlHasHttpsScheme (url) { + if (typeof url === 'string') { + return url.startsWith('https:') + } + + return url.protocol === 'https:' +} + +/** + * @see https://fetch.spec.whatwg.org/#http-scheme + * @param {URL} url + */ +function urlIsHttpHttpsScheme (url) { + assert('protocol' in url) // ensure it's a url object + + const protocol = url.protocol + + return protocol === 'http:' || protocol === 'https:' +} + +/** + * Fetch supports node >= 16.8.0, but Object.hasOwn was added in v16.9.0. + */ +const hasOwn = Object.hasOwn || ((dict, key) => Object.prototype.hasOwnProperty.call(dict, key)) + +module.exports = { + isAborted, + isCancelled, + createDeferredPromise, + ReadableStreamFrom, + toUSVString, + tryUpgradeRequestToAPotentiallyTrustworthyURL, + coarsenedSharedCurrentTime, + determineRequestsReferrer, + makePolicyContainer, + clonePolicyContainer, + appendFetchMetadata, + appendRequestOriginHeader, + TAOCheck, + corsCheck, + crossOriginResourcePolicyCheck, + createOpaqueTimingInfo, + setRequestReferrerPolicyOnRedirect, + isValidHTTPToken, + requestBadPort, + requestCurrentURL, + responseURL, + responseLocationURL, + isBlobLike, + isURLPotentiallyTrustworthy, + isValidReasonPhrase, + sameOrigin, + normalizeMethod, + serializeJavascriptValueToJSONString, + makeIterator, + isValidHeaderName, + isValidHeaderValue, + hasOwn, + isErrorLike, + fullyReadBody, + bytesMatch, + isReadableStreamLike, + readableStreamClose, + isomorphicEncode, + isomorphicDecode, + urlIsLocal, + urlHasHttpsScheme, + urlIsHttpHttpsScheme, + readAllBytes, + normalizeMethodRecord +} + + +/***/ }), + +/***/ 1537: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { types } = __nccwpck_require__(3837) +const { hasOwn, toUSVString } = __nccwpck_require__(784) + +/** @type {import('../../types/webidl').Webidl} */ +const webidl = {} +webidl.converters = {} +webidl.util = {} +webidl.errors = {} + +webidl.errors.exception = function (message) { + return new TypeError(`${message.header}: ${message.message}`) +} + +webidl.errors.conversionFailed = function (context) { + const plural = context.types.length === 1 ? '' : ' one of' + const message = + `${context.argument} could not be converted to` + + `${plural}: ${context.types.join(', ')}.` + + return webidl.errors.exception({ + header: context.prefix, + message + }) +} + +webidl.errors.invalidArgument = function (context) { + return webidl.errors.exception({ + header: context.prefix, + message: `"${context.value}" is an invalid ${context.type}.` + }) +} + +// https://webidl.spec.whatwg.org/#implements +webidl.brandCheck = function (V, I, opts = undefined) { + if (opts?.strict !== false && !(V instanceof I)) { + throw new TypeError('Illegal invocation') + } else { + return V?.[Symbol.toStringTag] === I.prototype[Symbol.toStringTag] + } +} + +webidl.argumentLengthCheck = function ({ length }, min, ctx) { + if (length < min) { + throw webidl.errors.exception({ + message: `${min} argument${min !== 1 ? 's' : ''} required, ` + + `but${length ? ' only' : ''} ${length} found.`, + ...ctx + }) + } +} + +webidl.illegalConstructor = function () { + throw webidl.errors.exception({ + header: 'TypeError', + message: 'Illegal constructor' + }) +} + +// https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values +webidl.util.Type = function (V) { + switch (typeof V) { + case 'undefined': return 'Undefined' + case 'boolean': return 'Boolean' + case 'string': return 'String' + case 'symbol': return 'Symbol' + case 'number': return 'Number' + case 'bigint': return 'BigInt' + case 'function': + case 'object': { + if (V === null) { + return 'Null' + } + + return 'Object' + } + } +} + +// https://webidl.spec.whatwg.org/#abstract-opdef-converttoint +webidl.util.ConvertToInt = function (V, bitLength, signedness, opts = {}) { + let upperBound + let lowerBound + + // 1. If bitLength is 64, then: + if (bitLength === 64) { + // 1. Let upperBound be 2^53 − 1. + upperBound = Math.pow(2, 53) - 1 + + // 2. If signedness is "unsigned", then let lowerBound be 0. + if (signedness === 'unsigned') { + lowerBound = 0 + } else { + // 3. Otherwise let lowerBound be −2^53 + 1. + lowerBound = Math.pow(-2, 53) + 1 + } + } else if (signedness === 'unsigned') { + // 2. Otherwise, if signedness is "unsigned", then: + + // 1. Let lowerBound be 0. + lowerBound = 0 + + // 2. Let upperBound be 2^bitLength − 1. + upperBound = Math.pow(2, bitLength) - 1 + } else { + // 3. Otherwise: + + // 1. Let lowerBound be -2^bitLength − 1. + lowerBound = Math.pow(-2, bitLength) - 1 + + // 2. Let upperBound be 2^bitLength − 1 − 1. + upperBound = Math.pow(2, bitLength - 1) - 1 + } + + // 4. Let x be ? ToNumber(V). + let x = Number(V) + + // 5. If x is −0, then set x to +0. + if (x === 0) { + x = 0 + } + + // 6. If the conversion is to an IDL type associated + // with the [EnforceRange] extended attribute, then: + if (opts.enforceRange === true) { + // 1. If x is NaN, +∞, or −∞, then throw a TypeError. + if ( + Number.isNaN(x) || + x === Number.POSITIVE_INFINITY || + x === Number.NEGATIVE_INFINITY + ) { + throw webidl.errors.exception({ + header: 'Integer conversion', + message: `Could not convert ${V} to an integer.` + }) + } + + // 2. Set x to IntegerPart(x). + x = webidl.util.IntegerPart(x) + + // 3. If x < lowerBound or x > upperBound, then + // throw a TypeError. + if (x < lowerBound || x > upperBound) { + throw webidl.errors.exception({ + header: 'Integer conversion', + message: `Value must be between ${lowerBound}-${upperBound}, got ${x}.` + }) + } + + // 4. Return x. + return x + } + + // 7. If x is not NaN and the conversion is to an IDL + // type associated with the [Clamp] extended + // attribute, then: + if (!Number.isNaN(x) && opts.clamp === true) { + // 1. Set x to min(max(x, lowerBound), upperBound). + x = Math.min(Math.max(x, lowerBound), upperBound) + + // 2. Round x to the nearest integer, choosing the + // even integer if it lies halfway between two, + // and choosing +0 rather than −0. + if (Math.floor(x) % 2 === 0) { + x = Math.floor(x) + } else { + x = Math.ceil(x) + } + + // 3. Return x. + return x + } + + // 8. If x is NaN, +0, +∞, or −∞, then return +0. + if ( + Number.isNaN(x) || + (x === 0 && Object.is(0, x)) || + x === Number.POSITIVE_INFINITY || + x === Number.NEGATIVE_INFINITY + ) { + return 0 + } + + // 9. Set x to IntegerPart(x). + x = webidl.util.IntegerPart(x) + + // 10. Set x to x modulo 2^bitLength. + x = x % Math.pow(2, bitLength) + + // 11. If signedness is "signed" and x ≥ 2^bitLength − 1, + // then return x − 2^bitLength. + if (signedness === 'signed' && x >= Math.pow(2, bitLength) - 1) { + return x - Math.pow(2, bitLength) + } + + // 12. Otherwise, return x. + return x +} + +// https://webidl.spec.whatwg.org/#abstract-opdef-integerpart +webidl.util.IntegerPart = function (n) { + // 1. Let r be floor(abs(n)). + const r = Math.floor(Math.abs(n)) + + // 2. If n < 0, then return -1 × r. + if (n < 0) { + return -1 * r + } + + // 3. Otherwise, return r. + return r +} + +// https://webidl.spec.whatwg.org/#es-sequence +webidl.sequenceConverter = function (converter) { + return (V) => { + // 1. If Type(V) is not Object, throw a TypeError. + if (webidl.util.Type(V) !== 'Object') { + throw webidl.errors.exception({ + header: 'Sequence', + message: `Value of type ${webidl.util.Type(V)} is not an Object.` + }) + } + + // 2. Let method be ? GetMethod(V, @@iterator). + /** @type {Generator} */ + const method = V?.[Symbol.iterator]?.() + const seq = [] + + // 3. If method is undefined, throw a TypeError. + if ( + method === undefined || + typeof method.next !== 'function' + ) { + throw webidl.errors.exception({ + header: 'Sequence', + message: 'Object is not an iterator.' + }) + } + + // https://webidl.spec.whatwg.org/#create-sequence-from-iterable + while (true) { + const { done, value } = method.next() + + if (done) { + break + } + + seq.push(converter(value)) + } + + return seq + } +} + +// https://webidl.spec.whatwg.org/#es-to-record +webidl.recordConverter = function (keyConverter, valueConverter) { + return (O) => { + // 1. If Type(O) is not Object, throw a TypeError. + if (webidl.util.Type(O) !== 'Object') { + throw webidl.errors.exception({ + header: 'Record', + message: `Value of type ${webidl.util.Type(O)} is not an Object.` + }) + } + + // 2. Let result be a new empty instance of record. + const result = {} + + if (!types.isProxy(O)) { + // Object.keys only returns enumerable properties + const keys = Object.keys(O) + + for (const key of keys) { + // 1. Let typedKey be key converted to an IDL value of type K. + const typedKey = keyConverter(key) + + // 2. Let value be ? Get(O, key). + // 3. Let typedValue be value converted to an IDL value of type V. + const typedValue = valueConverter(O[key]) + + // 4. Set result[typedKey] to typedValue. + result[typedKey] = typedValue + } + + // 5. Return result. + return result + } + + // 3. Let keys be ? O.[[OwnPropertyKeys]](). + const keys = Reflect.ownKeys(O) + + // 4. For each key of keys. + for (const key of keys) { + // 1. Let desc be ? O.[[GetOwnProperty]](key). + const desc = Reflect.getOwnPropertyDescriptor(O, key) + + // 2. If desc is not undefined and desc.[[Enumerable]] is true: + if (desc?.enumerable) { + // 1. Let typedKey be key converted to an IDL value of type K. + const typedKey = keyConverter(key) + + // 2. Let value be ? Get(O, key). + // 3. Let typedValue be value converted to an IDL value of type V. + const typedValue = valueConverter(O[key]) + + // 4. Set result[typedKey] to typedValue. + result[typedKey] = typedValue + } + } + + // 5. Return result. + return result + } +} + +webidl.interfaceConverter = function (i) { + return (V, opts = {}) => { + if (opts.strict !== false && !(V instanceof i)) { + throw webidl.errors.exception({ + header: i.name, + message: `Expected ${V} to be an instance of ${i.name}.` + }) + } + + return V + } +} + +webidl.dictionaryConverter = function (converters) { + return (dictionary) => { + const type = webidl.util.Type(dictionary) + const dict = {} + + if (type === 'Null' || type === 'Undefined') { + return dict + } else if (type !== 'Object') { + throw webidl.errors.exception({ + header: 'Dictionary', + message: `Expected ${dictionary} to be one of: Null, Undefined, Object.` + }) + } + + for (const options of converters) { + const { key, defaultValue, required, converter } = options + + if (required === true) { + if (!hasOwn(dictionary, key)) { + throw webidl.errors.exception({ + header: 'Dictionary', + message: `Missing required key "${key}".` + }) + } + } + + let value = dictionary[key] + const hasDefault = hasOwn(options, 'defaultValue') + + // Only use defaultValue if value is undefined and + // a defaultValue options was provided. + if (hasDefault && value !== null) { + value = value ?? defaultValue + } + + // A key can be optional and have no default value. + // When this happens, do not perform a conversion, + // and do not assign the key a value. + if (required || hasDefault || value !== undefined) { + value = converter(value) + + if ( + options.allowedValues && + !options.allowedValues.includes(value) + ) { + throw webidl.errors.exception({ + header: 'Dictionary', + message: `${value} is not an accepted type. Expected one of ${options.allowedValues.join(', ')}.` + }) + } + + dict[key] = value + } + } + + return dict + } +} + +webidl.nullableConverter = function (converter) { + return (V) => { + if (V === null) { + return V + } + + return converter(V) + } +} + +// https://webidl.spec.whatwg.org/#es-DOMString +webidl.converters.DOMString = function (V, opts = {}) { + // 1. If V is null and the conversion is to an IDL type + // associated with the [LegacyNullToEmptyString] + // extended attribute, then return the DOMString value + // that represents the empty string. + if (V === null && opts.legacyNullToEmptyString) { + return '' + } + + // 2. Let x be ? ToString(V). + if (typeof V === 'symbol') { + throw new TypeError('Could not convert argument of type symbol to string.') + } + + // 3. Return the IDL DOMString value that represents the + // same sequence of code units as the one the + // ECMAScript String value x represents. + return String(V) +} + +// https://webidl.spec.whatwg.org/#es-ByteString +webidl.converters.ByteString = function (V) { + // 1. Let x be ? ToString(V). + // Note: DOMString converter perform ? ToString(V) + const x = webidl.converters.DOMString(V) + + // 2. If the value of any element of x is greater than + // 255, then throw a TypeError. + for (let index = 0; index < x.length; index++) { + if (x.charCodeAt(index) > 255) { + throw new TypeError( + 'Cannot convert argument to a ByteString because the character at ' + + `index ${index} has a value of ${x.charCodeAt(index)} which is greater than 255.` + ) + } + } + + // 3. Return an IDL ByteString value whose length is the + // length of x, and where the value of each element is + // the value of the corresponding element of x. + return x +} + +// https://webidl.spec.whatwg.org/#es-USVString +webidl.converters.USVString = toUSVString + +// https://webidl.spec.whatwg.org/#es-boolean +webidl.converters.boolean = function (V) { + // 1. Let x be the result of computing ToBoolean(V). + const x = Boolean(V) + + // 2. Return the IDL boolean value that is the one that represents + // the same truth value as the ECMAScript Boolean value x. + return x +} + +// https://webidl.spec.whatwg.org/#es-any +webidl.converters.any = function (V) { + return V +} + +// https://webidl.spec.whatwg.org/#es-long-long +webidl.converters['long long'] = function (V) { + // 1. Let x be ? ConvertToInt(V, 64, "signed"). + const x = webidl.util.ConvertToInt(V, 64, 'signed') + + // 2. Return the IDL long long value that represents + // the same numeric value as x. + return x +} + +// https://webidl.spec.whatwg.org/#es-unsigned-long-long +webidl.converters['unsigned long long'] = function (V) { + // 1. Let x be ? ConvertToInt(V, 64, "unsigned"). + const x = webidl.util.ConvertToInt(V, 64, 'unsigned') + + // 2. Return the IDL unsigned long long value that + // represents the same numeric value as x. + return x +} + +// https://webidl.spec.whatwg.org/#es-unsigned-long +webidl.converters['unsigned long'] = function (V) { + // 1. Let x be ? ConvertToInt(V, 32, "unsigned"). + const x = webidl.util.ConvertToInt(V, 32, 'unsigned') + + // 2. Return the IDL unsigned long value that + // represents the same numeric value as x. + return x +} + +// https://webidl.spec.whatwg.org/#es-unsigned-short +webidl.converters['unsigned short'] = function (V, opts) { + // 1. Let x be ? ConvertToInt(V, 16, "unsigned"). + const x = webidl.util.ConvertToInt(V, 16, 'unsigned', opts) + + // 2. Return the IDL unsigned short value that represents + // the same numeric value as x. + return x +} + +// https://webidl.spec.whatwg.org/#idl-ArrayBuffer +webidl.converters.ArrayBuffer = function (V, opts = {}) { + // 1. If Type(V) is not Object, or V does not have an + // [[ArrayBufferData]] internal slot, then throw a + // TypeError. + // see: https://tc39.es/ecma262/#sec-properties-of-the-arraybuffer-instances + // see: https://tc39.es/ecma262/#sec-properties-of-the-sharedarraybuffer-instances + if ( + webidl.util.Type(V) !== 'Object' || + !types.isAnyArrayBuffer(V) + ) { + throw webidl.errors.conversionFailed({ + prefix: `${V}`, + argument: `${V}`, + types: ['ArrayBuffer'] + }) + } + + // 2. If the conversion is not to an IDL type associated + // with the [AllowShared] extended attribute, and + // IsSharedArrayBuffer(V) is true, then throw a + // TypeError. + if (opts.allowShared === false && types.isSharedArrayBuffer(V)) { + throw webidl.errors.exception({ + header: 'ArrayBuffer', + message: 'SharedArrayBuffer is not allowed.' + }) + } + + // 3. If the conversion is not to an IDL type associated + // with the [AllowResizable] extended attribute, and + // IsResizableArrayBuffer(V) is true, then throw a + // TypeError. + // Note: resizable ArrayBuffers are currently a proposal. + + // 4. Return the IDL ArrayBuffer value that is a + // reference to the same object as V. + return V +} + +webidl.converters.TypedArray = function (V, T, opts = {}) { + // 1. Let T be the IDL type V is being converted to. + + // 2. If Type(V) is not Object, or V does not have a + // [[TypedArrayName]] internal slot with a value + // equal to T’s name, then throw a TypeError. + if ( + webidl.util.Type(V) !== 'Object' || + !types.isTypedArray(V) || + V.constructor.name !== T.name + ) { + throw webidl.errors.conversionFailed({ + prefix: `${T.name}`, + argument: `${V}`, + types: [T.name] + }) + } + + // 3. If the conversion is not to an IDL type associated + // with the [AllowShared] extended attribute, and + // IsSharedArrayBuffer(V.[[ViewedArrayBuffer]]) is + // true, then throw a TypeError. + if (opts.allowShared === false && types.isSharedArrayBuffer(V.buffer)) { + throw webidl.errors.exception({ + header: 'ArrayBuffer', + message: 'SharedArrayBuffer is not allowed.' + }) + } + + // 4. If the conversion is not to an IDL type associated + // with the [AllowResizable] extended attribute, and + // IsResizableArrayBuffer(V.[[ViewedArrayBuffer]]) is + // true, then throw a TypeError. + // Note: resizable array buffers are currently a proposal + + // 5. Return the IDL value of type T that is a reference + // to the same object as V. + return V +} + +webidl.converters.DataView = function (V, opts = {}) { + // 1. If Type(V) is not Object, or V does not have a + // [[DataView]] internal slot, then throw a TypeError. + if (webidl.util.Type(V) !== 'Object' || !types.isDataView(V)) { + throw webidl.errors.exception({ + header: 'DataView', + message: 'Object is not a DataView.' + }) + } + + // 2. If the conversion is not to an IDL type associated + // with the [AllowShared] extended attribute, and + // IsSharedArrayBuffer(V.[[ViewedArrayBuffer]]) is true, + // then throw a TypeError. + if (opts.allowShared === false && types.isSharedArrayBuffer(V.buffer)) { + throw webidl.errors.exception({ + header: 'ArrayBuffer', + message: 'SharedArrayBuffer is not allowed.' + }) + } + + // 3. If the conversion is not to an IDL type associated + // with the [AllowResizable] extended attribute, and + // IsResizableArrayBuffer(V.[[ViewedArrayBuffer]]) is + // true, then throw a TypeError. + // Note: resizable ArrayBuffers are currently a proposal + + // 4. Return the IDL DataView value that is a reference + // to the same object as V. + return V +} + +// https://webidl.spec.whatwg.org/#BufferSource +webidl.converters.BufferSource = function (V, opts = {}) { + if (types.isAnyArrayBuffer(V)) { + return webidl.converters.ArrayBuffer(V, opts) + } + + if (types.isTypedArray(V)) { + return webidl.converters.TypedArray(V, V.constructor) + } + + if (types.isDataView(V)) { + return webidl.converters.DataView(V, opts) + } + + throw new TypeError(`Could not convert ${V} to a BufferSource.`) +} + +webidl.converters['sequence'] = webidl.sequenceConverter( + webidl.converters.ByteString +) + +webidl.converters['sequence>'] = webidl.sequenceConverter( + webidl.converters['sequence'] +) + +webidl.converters['record'] = webidl.recordConverter( + webidl.converters.ByteString, + webidl.converters.ByteString +) + +module.exports = { + webidl +} + + +/***/ }), + +/***/ 4605: +/***/ ((module) => { + +"use strict"; + + +/** + * @see https://encoding.spec.whatwg.org/#concept-encoding-get + * @param {string|undefined} label + */ +function getEncoding (label) { + if (!label) { + return 'failure' + } + + // 1. Remove any leading and trailing ASCII whitespace from label. + // 2. If label is an ASCII case-insensitive match for any of the + // labels listed in the table below, then return the + // corresponding encoding; otherwise return failure. + switch (label.trim().toLowerCase()) { + case 'unicode-1-1-utf-8': + case 'unicode11utf8': + case 'unicode20utf8': + case 'utf-8': + case 'utf8': + case 'x-unicode20utf8': + return 'UTF-8' + case '866': + case 'cp866': + case 'csibm866': + case 'ibm866': + return 'IBM866' + case 'csisolatin2': + case 'iso-8859-2': + case 'iso-ir-101': + case 'iso8859-2': + case 'iso88592': + case 'iso_8859-2': + case 'iso_8859-2:1987': + case 'l2': + case 'latin2': + return 'ISO-8859-2' + case 'csisolatin3': + case 'iso-8859-3': + case 'iso-ir-109': + case 'iso8859-3': + case 'iso88593': + case 'iso_8859-3': + case 'iso_8859-3:1988': + case 'l3': + case 'latin3': + return 'ISO-8859-3' + case 'csisolatin4': + case 'iso-8859-4': + case 'iso-ir-110': + case 'iso8859-4': + case 'iso88594': + case 'iso_8859-4': + case 'iso_8859-4:1988': + case 'l4': + case 'latin4': + return 'ISO-8859-4' + case 'csisolatincyrillic': + case 'cyrillic': + case 'iso-8859-5': + case 'iso-ir-144': + case 'iso8859-5': + case 'iso88595': + case 'iso_8859-5': + case 'iso_8859-5:1988': + return 'ISO-8859-5' + case 'arabic': + case 'asmo-708': + case 'csiso88596e': + case 'csiso88596i': + case 'csisolatinarabic': + case 'ecma-114': + case 'iso-8859-6': + case 'iso-8859-6-e': + case 'iso-8859-6-i': + case 'iso-ir-127': + case 'iso8859-6': + case 'iso88596': + case 'iso_8859-6': + case 'iso_8859-6:1987': + return 'ISO-8859-6' + case 'csisolatingreek': + case 'ecma-118': + case 'elot_928': + case 'greek': + case 'greek8': + case 'iso-8859-7': + case 'iso-ir-126': + case 'iso8859-7': + case 'iso88597': + case 'iso_8859-7': + case 'iso_8859-7:1987': + case 'sun_eu_greek': + return 'ISO-8859-7' + case 'csiso88598e': + case 'csisolatinhebrew': + case 'hebrew': + case 'iso-8859-8': + case 'iso-8859-8-e': + case 'iso-ir-138': + case 'iso8859-8': + case 'iso88598': + case 'iso_8859-8': + case 'iso_8859-8:1988': + case 'visual': + return 'ISO-8859-8' + case 'csiso88598i': + case 'iso-8859-8-i': + case 'logical': + return 'ISO-8859-8-I' + case 'csisolatin6': + case 'iso-8859-10': + case 'iso-ir-157': + case 'iso8859-10': + case 'iso885910': + case 'l6': + case 'latin6': + return 'ISO-8859-10' + case 'iso-8859-13': + case 'iso8859-13': + case 'iso885913': + return 'ISO-8859-13' + case 'iso-8859-14': + case 'iso8859-14': + case 'iso885914': + return 'ISO-8859-14' + case 'csisolatin9': + case 'iso-8859-15': + case 'iso8859-15': + case 'iso885915': + case 'iso_8859-15': + case 'l9': + return 'ISO-8859-15' + case 'iso-8859-16': + return 'ISO-8859-16' + case 'cskoi8r': + case 'koi': + case 'koi8': + case 'koi8-r': + case 'koi8_r': + return 'KOI8-R' + case 'koi8-ru': + case 'koi8-u': + return 'KOI8-U' + case 'csmacintosh': + case 'mac': + case 'macintosh': + case 'x-mac-roman': + return 'macintosh' + case 'iso-8859-11': + case 'iso8859-11': + case 'iso885911': + case 'tis-620': + case 'windows-874': + return 'windows-874' + case 'cp1250': + case 'windows-1250': + case 'x-cp1250': + return 'windows-1250' + case 'cp1251': + case 'windows-1251': + case 'x-cp1251': + return 'windows-1251' + case 'ansi_x3.4-1968': + case 'ascii': + case 'cp1252': + case 'cp819': + case 'csisolatin1': + case 'ibm819': + case 'iso-8859-1': + case 'iso-ir-100': + case 'iso8859-1': + case 'iso88591': + case 'iso_8859-1': + case 'iso_8859-1:1987': + case 'l1': + case 'latin1': + case 'us-ascii': + case 'windows-1252': + case 'x-cp1252': + return 'windows-1252' + case 'cp1253': + case 'windows-1253': + case 'x-cp1253': + return 'windows-1253' + case 'cp1254': + case 'csisolatin5': + case 'iso-8859-9': + case 'iso-ir-148': + case 'iso8859-9': + case 'iso88599': + case 'iso_8859-9': + case 'iso_8859-9:1989': + case 'l5': + case 'latin5': + case 'windows-1254': + case 'x-cp1254': + return 'windows-1254' + case 'cp1255': + case 'windows-1255': + case 'x-cp1255': + return 'windows-1255' + case 'cp1256': + case 'windows-1256': + case 'x-cp1256': + return 'windows-1256' + case 'cp1257': + case 'windows-1257': + case 'x-cp1257': + return 'windows-1257' + case 'cp1258': + case 'windows-1258': + case 'x-cp1258': + return 'windows-1258' + case 'x-mac-cyrillic': + case 'x-mac-ukrainian': + return 'x-mac-cyrillic' + case 'chinese': + case 'csgb2312': + case 'csiso58gb231280': + case 'gb2312': + case 'gb_2312': + case 'gb_2312-80': + case 'gbk': + case 'iso-ir-58': + case 'x-gbk': + return 'GBK' + case 'gb18030': + return 'gb18030' + case 'big5': + case 'big5-hkscs': + case 'cn-big5': + case 'csbig5': + case 'x-x-big5': + return 'Big5' + case 'cseucpkdfmtjapanese': + case 'euc-jp': + case 'x-euc-jp': + return 'EUC-JP' + case 'csiso2022jp': + case 'iso-2022-jp': + return 'ISO-2022-JP' + case 'csshiftjis': + case 'ms932': + case 'ms_kanji': + case 'shift-jis': + case 'shift_jis': + case 'sjis': + case 'windows-31j': + case 'x-sjis': + return 'Shift_JIS' + case 'cseuckr': + case 'csksc56011987': + case 'euc-kr': + case 'iso-ir-149': + case 'korean': + case 'ks_c_5601-1987': + case 'ks_c_5601-1989': + case 'ksc5601': + case 'ksc_5601': + case 'windows-949': + return 'EUC-KR' + case 'csiso2022kr': + case 'hz-gb-2312': + case 'iso-2022-cn': + case 'iso-2022-cn-ext': + case 'iso-2022-kr': + case 'replacement': + return 'replacement' + case 'unicodefffe': + case 'utf-16be': + return 'UTF-16BE' + case 'csunicode': + case 'iso-10646-ucs-2': + case 'ucs-2': + case 'unicode': + case 'unicodefeff': + case 'utf-16': + case 'utf-16le': + return 'UTF-16LE' + case 'x-user-defined': + return 'x-user-defined' + default: return 'failure' + } +} + +module.exports = { + getEncoding +} + + +/***/ }), + +/***/ 9339: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { + staticPropertyDescriptors, + readOperation, + fireAProgressEvent +} = __nccwpck_require__(5813) +const { + kState, + kError, + kResult, + kEvents, + kAborted +} = __nccwpck_require__(4097) +const { webidl } = __nccwpck_require__(1537) +const { kEnumerableProperty } = __nccwpck_require__(9522) + +class FileReader extends EventTarget { + constructor () { + super() + + this[kState] = 'empty' + this[kResult] = null + this[kError] = null + this[kEvents] = { + loadend: null, + error: null, + abort: null, + load: null, + progress: null, + loadstart: null + } + } + + /** + * @see https://w3c.github.io/FileAPI/#dfn-readAsArrayBuffer + * @param {import('buffer').Blob} blob + */ + readAsArrayBuffer (blob) { + webidl.brandCheck(this, FileReader) + + webidl.argumentLengthCheck(arguments, 1, { header: 'FileReader.readAsArrayBuffer' }) + + blob = webidl.converters.Blob(blob, { strict: false }) + + // The readAsArrayBuffer(blob) method, when invoked, + // must initiate a read operation for blob with ArrayBuffer. + readOperation(this, blob, 'ArrayBuffer') + } + + /** + * @see https://w3c.github.io/FileAPI/#readAsBinaryString + * @param {import('buffer').Blob} blob + */ + readAsBinaryString (blob) { + webidl.brandCheck(this, FileReader) + + webidl.argumentLengthCheck(arguments, 1, { header: 'FileReader.readAsBinaryString' }) + + blob = webidl.converters.Blob(blob, { strict: false }) + + // The readAsBinaryString(blob) method, when invoked, + // must initiate a read operation for blob with BinaryString. + readOperation(this, blob, 'BinaryString') + } + + /** + * @see https://w3c.github.io/FileAPI/#readAsDataText + * @param {import('buffer').Blob} blob + * @param {string?} encoding + */ + readAsText (blob, encoding = undefined) { + webidl.brandCheck(this, FileReader) + + webidl.argumentLengthCheck(arguments, 1, { header: 'FileReader.readAsText' }) + + blob = webidl.converters.Blob(blob, { strict: false }) + + if (encoding !== undefined) { + encoding = webidl.converters.DOMString(encoding) + } + + // The readAsText(blob, encoding) method, when invoked, + // must initiate a read operation for blob with Text and encoding. + readOperation(this, blob, 'Text', encoding) + } + + /** + * @see https://w3c.github.io/FileAPI/#dfn-readAsDataURL + * @param {import('buffer').Blob} blob + */ + readAsDataURL (blob) { + webidl.brandCheck(this, FileReader) + + webidl.argumentLengthCheck(arguments, 1, { header: 'FileReader.readAsDataURL' }) + + blob = webidl.converters.Blob(blob, { strict: false }) + + // The readAsDataURL(blob) method, when invoked, must + // initiate a read operation for blob with DataURL. + readOperation(this, blob, 'DataURL') + } + + /** + * @see https://w3c.github.io/FileAPI/#dfn-abort + */ + abort () { + // 1. If this's state is "empty" or if this's state is + // "done" set this's result to null and terminate + // this algorithm. + if (this[kState] === 'empty' || this[kState] === 'done') { + this[kResult] = null + return + } + + // 2. If this's state is "loading" set this's state to + // "done" and set this's result to null. + if (this[kState] === 'loading') { + this[kState] = 'done' + this[kResult] = null + } + + // 3. If there are any tasks from this on the file reading + // task source in an affiliated task queue, then remove + // those tasks from that task queue. + this[kAborted] = true + + // 4. Terminate the algorithm for the read method being processed. + // TODO + + // 5. Fire a progress event called abort at this. + fireAProgressEvent('abort', this) + + // 6. If this's state is not "loading", fire a progress + // event called loadend at this. + if (this[kState] !== 'loading') { + fireAProgressEvent('loadend', this) + } + } + + /** + * @see https://w3c.github.io/FileAPI/#dom-filereader-readystate + */ + get readyState () { + webidl.brandCheck(this, FileReader) + + switch (this[kState]) { + case 'empty': return this.EMPTY + case 'loading': return this.LOADING + case 'done': return this.DONE + } + } + + /** + * @see https://w3c.github.io/FileAPI/#dom-filereader-result + */ + get result () { + webidl.brandCheck(this, FileReader) + + // The result attribute’s getter, when invoked, must return + // this's result. + return this[kResult] + } + + /** + * @see https://w3c.github.io/FileAPI/#dom-filereader-error + */ + get error () { + webidl.brandCheck(this, FileReader) + + // The error attribute’s getter, when invoked, must return + // this's error. + return this[kError] + } + + get onloadend () { + webidl.brandCheck(this, FileReader) + + return this[kEvents].loadend + } + + set onloadend (fn) { + webidl.brandCheck(this, FileReader) + + if (this[kEvents].loadend) { + this.removeEventListener('loadend', this[kEvents].loadend) + } + + if (typeof fn === 'function') { + this[kEvents].loadend = fn + this.addEventListener('loadend', fn) + } else { + this[kEvents].loadend = null + } + } + + get onerror () { + webidl.brandCheck(this, FileReader) + + return this[kEvents].error + } + + set onerror (fn) { + webidl.brandCheck(this, FileReader) + + if (this[kEvents].error) { + this.removeEventListener('error', this[kEvents].error) + } + + if (typeof fn === 'function') { + this[kEvents].error = fn + this.addEventListener('error', fn) + } else { + this[kEvents].error = null + } + } + + get onloadstart () { + webidl.brandCheck(this, FileReader) + + return this[kEvents].loadstart + } + + set onloadstart (fn) { + webidl.brandCheck(this, FileReader) + + if (this[kEvents].loadstart) { + this.removeEventListener('loadstart', this[kEvents].loadstart) + } + + if (typeof fn === 'function') { + this[kEvents].loadstart = fn + this.addEventListener('loadstart', fn) + } else { + this[kEvents].loadstart = null + } + } + + get onprogress () { + webidl.brandCheck(this, FileReader) + + return this[kEvents].progress + } + + set onprogress (fn) { + webidl.brandCheck(this, FileReader) + + if (this[kEvents].progress) { + this.removeEventListener('progress', this[kEvents].progress) + } + + if (typeof fn === 'function') { + this[kEvents].progress = fn + this.addEventListener('progress', fn) + } else { + this[kEvents].progress = null + } + } + + get onload () { + webidl.brandCheck(this, FileReader) + + return this[kEvents].load + } + + set onload (fn) { + webidl.brandCheck(this, FileReader) + + if (this[kEvents].load) { + this.removeEventListener('load', this[kEvents].load) + } + + if (typeof fn === 'function') { + this[kEvents].load = fn + this.addEventListener('load', fn) + } else { + this[kEvents].load = null + } + } + + get onabort () { + webidl.brandCheck(this, FileReader) + + return this[kEvents].abort + } + + set onabort (fn) { + webidl.brandCheck(this, FileReader) + + if (this[kEvents].abort) { + this.removeEventListener('abort', this[kEvents].abort) + } + + if (typeof fn === 'function') { + this[kEvents].abort = fn + this.addEventListener('abort', fn) + } else { + this[kEvents].abort = null + } + } +} + +// https://w3c.github.io/FileAPI/#dom-filereader-empty +FileReader.EMPTY = FileReader.prototype.EMPTY = 0 +// https://w3c.github.io/FileAPI/#dom-filereader-loading +FileReader.LOADING = FileReader.prototype.LOADING = 1 +// https://w3c.github.io/FileAPI/#dom-filereader-done +FileReader.DONE = FileReader.prototype.DONE = 2 + +Object.defineProperties(FileReader.prototype, { + EMPTY: staticPropertyDescriptors, + LOADING: staticPropertyDescriptors, + DONE: staticPropertyDescriptors, + readAsArrayBuffer: kEnumerableProperty, + readAsBinaryString: kEnumerableProperty, + readAsText: kEnumerableProperty, + readAsDataURL: kEnumerableProperty, + abort: kEnumerableProperty, + readyState: kEnumerableProperty, + result: kEnumerableProperty, + error: kEnumerableProperty, + onloadstart: kEnumerableProperty, + onprogress: kEnumerableProperty, + onload: kEnumerableProperty, + onabort: kEnumerableProperty, + onerror: kEnumerableProperty, + onloadend: kEnumerableProperty, + [Symbol.toStringTag]: { + value: 'FileReader', + writable: false, + enumerable: false, + configurable: true + } +}) + +Object.defineProperties(FileReader, { + EMPTY: staticPropertyDescriptors, + LOADING: staticPropertyDescriptors, + DONE: staticPropertyDescriptors +}) + +module.exports = { + FileReader +} + + +/***/ }), + +/***/ 8343: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { webidl } = __nccwpck_require__(1537) + +const kState = Symbol('ProgressEvent state') + +/** + * @see https://xhr.spec.whatwg.org/#progressevent + */ +class ProgressEvent extends Event { + constructor (type, eventInitDict = {}) { + type = webidl.converters.DOMString(type) + eventInitDict = webidl.converters.ProgressEventInit(eventInitDict ?? {}) + + super(type, eventInitDict) + + this[kState] = { + lengthComputable: eventInitDict.lengthComputable, + loaded: eventInitDict.loaded, + total: eventInitDict.total + } + } + + get lengthComputable () { + webidl.brandCheck(this, ProgressEvent) + + return this[kState].lengthComputable + } + + get loaded () { + webidl.brandCheck(this, ProgressEvent) + + return this[kState].loaded + } + + get total () { + webidl.brandCheck(this, ProgressEvent) + + return this[kState].total + } +} + +webidl.converters.ProgressEventInit = webidl.dictionaryConverter([ + { + key: 'lengthComputable', + converter: webidl.converters.boolean, + defaultValue: false + }, + { + key: 'loaded', + converter: webidl.converters['unsigned long long'], + defaultValue: 0 + }, + { + key: 'total', + converter: webidl.converters['unsigned long long'], + defaultValue: 0 + }, + { + key: 'bubbles', + converter: webidl.converters.boolean, + defaultValue: false + }, + { + key: 'cancelable', + converter: webidl.converters.boolean, + defaultValue: false + }, + { + key: 'composed', + converter: webidl.converters.boolean, + defaultValue: false + } +]) + +module.exports = { + ProgressEvent +} + + +/***/ }), + +/***/ 4097: +/***/ ((module) => { + +"use strict"; + + +module.exports = { + kState: Symbol('FileReader state'), + kResult: Symbol('FileReader result'), + kError: Symbol('FileReader error'), + kLastProgressEventFired: Symbol('FileReader last progress event fired timestamp'), + kEvents: Symbol('FileReader events'), + kAborted: Symbol('FileReader aborted') +} + + +/***/ }), + +/***/ 5813: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { + kState, + kError, + kResult, + kAborted, + kLastProgressEventFired +} = __nccwpck_require__(4097) +const { ProgressEvent } = __nccwpck_require__(8343) +const { getEncoding } = __nccwpck_require__(4605) +const { DOMException } = __nccwpck_require__(7059) +const { serializeAMimeType, parseMIMEType } = __nccwpck_require__(2791) +const { types } = __nccwpck_require__(3837) +const { StringDecoder } = __nccwpck_require__(1576) +const { btoa } = __nccwpck_require__(4300) + +/** @type {PropertyDescriptor} */ +const staticPropertyDescriptors = { + enumerable: true, + writable: false, + configurable: false +} + +/** + * @see https://w3c.github.io/FileAPI/#readOperation + * @param {import('./filereader').FileReader} fr + * @param {import('buffer').Blob} blob + * @param {string} type + * @param {string?} encodingName + */ +function readOperation (fr, blob, type, encodingName) { + // 1. If fr’s state is "loading", throw an InvalidStateError + // DOMException. + if (fr[kState] === 'loading') { + throw new DOMException('Invalid state', 'InvalidStateError') + } + + // 2. Set fr’s state to "loading". + fr[kState] = 'loading' + + // 3. Set fr’s result to null. + fr[kResult] = null + + // 4. Set fr’s error to null. + fr[kError] = null + + // 5. Let stream be the result of calling get stream on blob. + /** @type {import('stream/web').ReadableStream} */ + const stream = blob.stream() + + // 6. Let reader be the result of getting a reader from stream. + const reader = stream.getReader() + + // 7. Let bytes be an empty byte sequence. + /** @type {Uint8Array[]} */ + const bytes = [] + + // 8. Let chunkPromise be the result of reading a chunk from + // stream with reader. + let chunkPromise = reader.read() + + // 9. Let isFirstChunk be true. + let isFirstChunk = true + + // 10. In parallel, while true: + // Note: "In parallel" just means non-blocking + // Note 2: readOperation itself cannot be async as double + // reading the body would then reject the promise, instead + // of throwing an error. + ;(async () => { + while (!fr[kAborted]) { + // 1. Wait for chunkPromise to be fulfilled or rejected. + try { + const { done, value } = await chunkPromise + + // 2. If chunkPromise is fulfilled, and isFirstChunk is + // true, queue a task to fire a progress event called + // loadstart at fr. + if (isFirstChunk && !fr[kAborted]) { + queueMicrotask(() => { + fireAProgressEvent('loadstart', fr) + }) + } + + // 3. Set isFirstChunk to false. + isFirstChunk = false + + // 4. If chunkPromise is fulfilled with an object whose + // done property is false and whose value property is + // a Uint8Array object, run these steps: + if (!done && types.isUint8Array(value)) { + // 1. Let bs be the byte sequence represented by the + // Uint8Array object. + + // 2. Append bs to bytes. + bytes.push(value) + + // 3. If roughly 50ms have passed since these steps + // were last invoked, queue a task to fire a + // progress event called progress at fr. + if ( + ( + fr[kLastProgressEventFired] === undefined || + Date.now() - fr[kLastProgressEventFired] >= 50 + ) && + !fr[kAborted] + ) { + fr[kLastProgressEventFired] = Date.now() + queueMicrotask(() => { + fireAProgressEvent('progress', fr) + }) + } + + // 4. Set chunkPromise to the result of reading a + // chunk from stream with reader. + chunkPromise = reader.read() + } else if (done) { + // 5. Otherwise, if chunkPromise is fulfilled with an + // object whose done property is true, queue a task + // to run the following steps and abort this algorithm: + queueMicrotask(() => { + // 1. Set fr’s state to "done". + fr[kState] = 'done' + + // 2. Let result be the result of package data given + // bytes, type, blob’s type, and encodingName. + try { + const result = packageData(bytes, type, blob.type, encodingName) + + // 4. Else: + + if (fr[kAborted]) { + return + } + + // 1. Set fr’s result to result. + fr[kResult] = result + + // 2. Fire a progress event called load at the fr. + fireAProgressEvent('load', fr) + } catch (error) { + // 3. If package data threw an exception error: + + // 1. Set fr’s error to error. + fr[kError] = error + + // 2. Fire a progress event called error at fr. + fireAProgressEvent('error', fr) + } + + // 5. If fr’s state is not "loading", fire a progress + // event called loadend at the fr. + if (fr[kState] !== 'loading') { + fireAProgressEvent('loadend', fr) + } + }) + + break + } + } catch (error) { + if (fr[kAborted]) { + return + } + + // 6. Otherwise, if chunkPromise is rejected with an + // error error, queue a task to run the following + // steps and abort this algorithm: + queueMicrotask(() => { + // 1. Set fr’s state to "done". + fr[kState] = 'done' + + // 2. Set fr’s error to error. + fr[kError] = error + + // 3. Fire a progress event called error at fr. + fireAProgressEvent('error', fr) + + // 4. If fr’s state is not "loading", fire a progress + // event called loadend at fr. + if (fr[kState] !== 'loading') { + fireAProgressEvent('loadend', fr) + } + }) + + break + } + } + })() +} + +/** + * @see https://w3c.github.io/FileAPI/#fire-a-progress-event + * @see https://dom.spec.whatwg.org/#concept-event-fire + * @param {string} e The name of the event + * @param {import('./filereader').FileReader} reader + */ +function fireAProgressEvent (e, reader) { + // The progress event e does not bubble. e.bubbles must be false + // The progress event e is NOT cancelable. e.cancelable must be false + const event = new ProgressEvent(e, { + bubbles: false, + cancelable: false + }) + + reader.dispatchEvent(event) +} + +/** + * @see https://w3c.github.io/FileAPI/#blob-package-data + * @param {Uint8Array[]} bytes + * @param {string} type + * @param {string?} mimeType + * @param {string?} encodingName + */ +function packageData (bytes, type, mimeType, encodingName) { + // 1. A Blob has an associated package data algorithm, given + // bytes, a type, a optional mimeType, and a optional + // encodingName, which switches on type and runs the + // associated steps: + + switch (type) { + case 'DataURL': { + // 1. Return bytes as a DataURL [RFC2397] subject to + // the considerations below: + // * Use mimeType as part of the Data URL if it is + // available in keeping with the Data URL + // specification [RFC2397]. + // * If mimeType is not available return a Data URL + // without a media-type. [RFC2397]. + + // https://datatracker.ietf.org/doc/html/rfc2397#section-3 + // dataurl := "data:" [ mediatype ] [ ";base64" ] "," data + // mediatype := [ type "/" subtype ] *( ";" parameter ) + // data := *urlchar + // parameter := attribute "=" value + let dataURL = 'data:' + + const parsed = parseMIMEType(mimeType || 'application/octet-stream') + + if (parsed !== 'failure') { + dataURL += serializeAMimeType(parsed) + } + + dataURL += ';base64,' + + const decoder = new StringDecoder('latin1') + + for (const chunk of bytes) { + dataURL += btoa(decoder.write(chunk)) + } + + dataURL += btoa(decoder.end()) + + return dataURL + } + case 'Text': { + // 1. Let encoding be failure + let encoding = 'failure' + + // 2. If the encodingName is present, set encoding to the + // result of getting an encoding from encodingName. + if (encodingName) { + encoding = getEncoding(encodingName) + } + + // 3. If encoding is failure, and mimeType is present: + if (encoding === 'failure' && mimeType) { + // 1. Let type be the result of parse a MIME type + // given mimeType. + const type = parseMIMEType(mimeType) + + // 2. If type is not failure, set encoding to the result + // of getting an encoding from type’s parameters["charset"]. + if (type !== 'failure') { + encoding = getEncoding(type.parameters.get('charset')) + } + } + + // 4. If encoding is failure, then set encoding to UTF-8. + if (encoding === 'failure') { + encoding = 'UTF-8' + } + + // 5. Decode bytes using fallback encoding encoding, and + // return the result. + return decode(bytes, encoding) + } + case 'ArrayBuffer': { + // Return a new ArrayBuffer whose contents are bytes. + const sequence = combineByteSequences(bytes) + + return sequence.buffer + } + case 'BinaryString': { + // Return bytes as a binary string, in which every byte + // is represented by a code unit of equal value [0..255]. + let binaryString = '' + + const decoder = new StringDecoder('latin1') + + for (const chunk of bytes) { + binaryString += decoder.write(chunk) + } + + binaryString += decoder.end() + + return binaryString + } + } +} + +/** + * @see https://encoding.spec.whatwg.org/#decode + * @param {Uint8Array[]} ioQueue + * @param {string} encoding + */ +function decode (ioQueue, encoding) { + const bytes = combineByteSequences(ioQueue) + + // 1. Let BOMEncoding be the result of BOM sniffing ioQueue. + const BOMEncoding = BOMSniffing(bytes) + + let slice = 0 + + // 2. If BOMEncoding is non-null: + if (BOMEncoding !== null) { + // 1. Set encoding to BOMEncoding. + encoding = BOMEncoding + + // 2. Read three bytes from ioQueue, if BOMEncoding is + // UTF-8; otherwise read two bytes. + // (Do nothing with those bytes.) + slice = BOMEncoding === 'UTF-8' ? 3 : 2 + } + + // 3. Process a queue with an instance of encoding’s + // decoder, ioQueue, output, and "replacement". + + // 4. Return output. + + const sliced = bytes.slice(slice) + return new TextDecoder(encoding).decode(sliced) +} + +/** + * @see https://encoding.spec.whatwg.org/#bom-sniff + * @param {Uint8Array} ioQueue + */ +function BOMSniffing (ioQueue) { + // 1. Let BOM be the result of peeking 3 bytes from ioQueue, + // converted to a byte sequence. + const [a, b, c] = ioQueue + + // 2. For each of the rows in the table below, starting with + // the first one and going down, if BOM starts with the + // bytes given in the first column, then return the + // encoding given in the cell in the second column of that + // row. Otherwise, return null. + if (a === 0xEF && b === 0xBB && c === 0xBF) { + return 'UTF-8' + } else if (a === 0xFE && b === 0xFF) { + return 'UTF-16BE' + } else if (a === 0xFF && b === 0xFE) { + return 'UTF-16LE' + } + + return null +} + +/** + * @param {Uint8Array[]} sequences + */ +function combineByteSequences (sequences) { + const size = sequences.reduce((a, b) => { + return a + b.byteLength + }, 0) + + let offset = 0 + + return sequences.reduce((a, b) => { + a.set(b, offset) + offset += b.byteLength + return a + }, new Uint8Array(size)) +} + +module.exports = { + staticPropertyDescriptors, + readOperation, + fireAProgressEvent +} + + +/***/ }), + +/***/ 5035: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +// We include a version number for the Dispatcher API. In case of breaking changes, +// this version number must be increased to avoid conflicts. +const globalDispatcher = Symbol.for('undici.globalDispatcher.1') +const { InvalidArgumentError } = __nccwpck_require__(721) +const Agent = __nccwpck_require__(8596) + +if (getGlobalDispatcher() === undefined) { + setGlobalDispatcher(new Agent()) +} + +function setGlobalDispatcher (agent) { + if (!agent || typeof agent.dispatch !== 'function') { + throw new InvalidArgumentError('Argument agent must implement Agent') + } + Object.defineProperty(globalThis, globalDispatcher, { + value: agent, + writable: true, + enumerable: false, + configurable: false + }) +} + +function getGlobalDispatcher () { + return globalThis[globalDispatcher] +} + +module.exports = { + setGlobalDispatcher, + getGlobalDispatcher +} + + +/***/ }), + +/***/ 194: +/***/ ((module) => { + +"use strict"; + + +module.exports = class DecoratorHandler { + constructor (handler) { + this.handler = handler + } + + onConnect (...args) { + return this.handler.onConnect(...args) + } + + onError (...args) { + return this.handler.onError(...args) + } + + onUpgrade (...args) { + return this.handler.onUpgrade(...args) + } + + onHeaders (...args) { + return this.handler.onHeaders(...args) + } + + onData (...args) { + return this.handler.onData(...args) + } + + onComplete (...args) { + return this.handler.onComplete(...args) + } + + onBodySent (...args) { + return this.handler.onBodySent(...args) + } +} + + +/***/ }), + +/***/ 7491: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const util = __nccwpck_require__(9522) +const { kBodyUsed } = __nccwpck_require__(9440) +const assert = __nccwpck_require__(9491) +const { InvalidArgumentError } = __nccwpck_require__(721) +const EE = __nccwpck_require__(2361) + +const redirectableStatusCodes = [300, 301, 302, 303, 307, 308] + +const kBody = Symbol('body') + +class BodyAsyncIterable { + constructor (body) { + this[kBody] = body + this[kBodyUsed] = false + } + + async * [Symbol.asyncIterator] () { + assert(!this[kBodyUsed], 'disturbed') + this[kBodyUsed] = true + yield * this[kBody] + } +} + +class RedirectHandler { + constructor (dispatch, maxRedirections, opts, handler) { + if (maxRedirections != null && (!Number.isInteger(maxRedirections) || maxRedirections < 0)) { + throw new InvalidArgumentError('maxRedirections must be a positive number') + } + + util.validateHandler(handler, opts.method, opts.upgrade) + + this.dispatch = dispatch + this.location = null + this.abort = null + this.opts = { ...opts, maxRedirections: 0 } // opts must be a copy + this.maxRedirections = maxRedirections + this.handler = handler + this.history = [] + + if (util.isStream(this.opts.body)) { + // TODO (fix): Provide some way for the user to cache the file to e.g. /tmp + // so that it can be dispatched again? + // TODO (fix): Do we need 100-expect support to provide a way to do this properly? + if (util.bodyLength(this.opts.body) === 0) { + this.opts.body + .on('data', function () { + assert(false) + }) + } + + if (typeof this.opts.body.readableDidRead !== 'boolean') { + this.opts.body[kBodyUsed] = false + EE.prototype.on.call(this.opts.body, 'data', function () { + this[kBodyUsed] = true + }) + } + } else if (this.opts.body && typeof this.opts.body.pipeTo === 'function') { + // TODO (fix): We can't access ReadableStream internal state + // to determine whether or not it has been disturbed. This is just + // a workaround. + this.opts.body = new BodyAsyncIterable(this.opts.body) + } else if ( + this.opts.body && + typeof this.opts.body !== 'string' && + !ArrayBuffer.isView(this.opts.body) && + util.isIterable(this.opts.body) + ) { + // TODO: Should we allow re-using iterable if !this.opts.idempotent + // or through some other flag? + this.opts.body = new BodyAsyncIterable(this.opts.body) + } + } + + onConnect (abort) { + this.abort = abort + this.handler.onConnect(abort, { history: this.history }) + } + + onUpgrade (statusCode, headers, socket) { + this.handler.onUpgrade(statusCode, headers, socket) + } + + onError (error) { + this.handler.onError(error) + } + + onHeaders (statusCode, headers, resume, statusText) { + this.location = this.history.length >= this.maxRedirections || util.isDisturbed(this.opts.body) + ? null + : parseLocation(statusCode, headers) + + if (this.opts.origin) { + this.history.push(new URL(this.opts.path, this.opts.origin)) + } + + if (!this.location) { + return this.handler.onHeaders(statusCode, headers, resume, statusText) + } + + const { origin, pathname, search } = util.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin))) + const path = search ? `${pathname}${search}` : pathname + + // Remove headers referring to the original URL. + // By default it is Host only, unless it's a 303 (see below), which removes also all Content-* headers. + // https://tools.ietf.org/html/rfc7231#section-6.4 + this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin) + this.opts.path = path + this.opts.origin = origin + this.opts.maxRedirections = 0 + this.opts.query = null + + // https://tools.ietf.org/html/rfc7231#section-6.4.4 + // In case of HTTP 303, always replace method to be either HEAD or GET + if (statusCode === 303 && this.opts.method !== 'HEAD') { + this.opts.method = 'GET' + this.opts.body = null + } + } + + onData (chunk) { + if (this.location) { + /* + https://tools.ietf.org/html/rfc7231#section-6.4 + + TLDR: undici always ignores 3xx response bodies. + + Redirection is used to serve the requested resource from another URL, so it is assumes that + no body is generated (and thus can be ignored). Even though generating a body is not prohibited. + + For status 301, 302, 303, 307 and 308 (the latter from RFC 7238), the specs mention that the body usually + (which means it's optional and not mandated) contain just an hyperlink to the value of + the Location response header, so the body can be ignored safely. + + For status 300, which is "Multiple Choices", the spec mentions both generating a Location + response header AND a response body with the other possible location to follow. + Since the spec explicitily chooses not to specify a format for such body and leave it to + servers and browsers implementors, we ignore the body as there is no specified way to eventually parse it. + */ + } else { + return this.handler.onData(chunk) + } + } + + onComplete (trailers) { + if (this.location) { + /* + https://tools.ietf.org/html/rfc7231#section-6.4 + + TLDR: undici always ignores 3xx response trailers as they are not expected in case of redirections + and neither are useful if present. + + See comment on onData method above for more detailed informations. + */ + + this.location = null + this.abort = null + + this.dispatch(this.opts, this) + } else { + this.handler.onComplete(trailers) + } + } + + onBodySent (chunk) { + if (this.handler.onBodySent) { + this.handler.onBodySent(chunk) + } + } +} + +function parseLocation (statusCode, headers) { + if (redirectableStatusCodes.indexOf(statusCode) === -1) { + return null + } + + for (let i = 0; i < headers.length; i += 2) { + if (headers[i].toString().toLowerCase() === 'location') { + return headers[i + 1] + } + } +} + +// https://tools.ietf.org/html/rfc7231#section-6.4.4 +function shouldRemoveHeader (header, removeContent, unknownOrigin) { + return ( + (header.length === 4 && header.toString().toLowerCase() === 'host') || + (removeContent && header.toString().toLowerCase().indexOf('content-') === 0) || + (unknownOrigin && header.length === 13 && header.toString().toLowerCase() === 'authorization') || + (unknownOrigin && header.length === 6 && header.toString().toLowerCase() === 'cookie') + ) +} + +// https://tools.ietf.org/html/rfc7231#section-6.4 +function cleanRequestHeaders (headers, removeContent, unknownOrigin) { + const ret = [] + if (Array.isArray(headers)) { + for (let i = 0; i < headers.length; i += 2) { + if (!shouldRemoveHeader(headers[i], removeContent, unknownOrigin)) { + ret.push(headers[i], headers[i + 1]) + } + } + } else if (headers && typeof headers === 'object') { + for (const key of Object.keys(headers)) { + if (!shouldRemoveHeader(key, removeContent, unknownOrigin)) { + ret.push(key, headers[key]) + } + } + } else { + assert(headers == null, 'headers must be an object or an array') + } + return ret +} + +module.exports = RedirectHandler + + +/***/ }), + +/***/ 5764: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +const assert = __nccwpck_require__(8061) + +const { kRetryHandlerDefaultRetry } = __nccwpck_require__(9440) +const { RequestRetryError } = __nccwpck_require__(721) +const { isDisturbed, parseHeaders, parseRangeHeader } = __nccwpck_require__(9522) + +function calculateRetryAfterHeader (retryAfter) { + const current = Date.now() + const diff = new Date(retryAfter).getTime() - current + + return diff +} + +class RetryHandler { + constructor (opts, handlers) { + const { retryOptions, ...dispatchOpts } = opts + const { + // Retry scoped + retry: retryFn, + maxRetries, + maxTimeout, + minTimeout, + timeoutFactor, + // Response scoped + methods, + errorCodes, + retryAfter, + statusCodes + } = retryOptions ?? {} + + this.dispatch = handlers.dispatch + this.handler = handlers.handler + this.opts = dispatchOpts + this.abort = null + this.aborted = false + this.retryOpts = { + retry: retryFn ?? RetryHandler[kRetryHandlerDefaultRetry], + retryAfter: retryAfter ?? true, + maxTimeout: maxTimeout ?? 30 * 1000, // 30s, + timeout: minTimeout ?? 500, // .5s + timeoutFactor: timeoutFactor ?? 2, + maxRetries: maxRetries ?? 5, + // What errors we should retry + methods: methods ?? ['GET', 'HEAD', 'OPTIONS', 'PUT', 'DELETE', 'TRACE'], + // Indicates which errors to retry + statusCodes: statusCodes ?? [500, 502, 503, 504, 429], + // List of errors to retry + errorCodes: errorCodes ?? [ + 'ECONNRESET', + 'ECONNREFUSED', + 'ENOTFOUND', + 'ENETDOWN', + 'ENETUNREACH', + 'EHOSTDOWN', + 'EHOSTUNREACH', + 'EPIPE' + ] + } + + this.retryCount = 0 + this.start = 0 + this.end = null + this.etag = null + this.resume = null + + // Handle possible onConnect duplication + this.handler.onConnect(reason => { + this.aborted = true + if (this.abort) { + this.abort(reason) + } else { + this.reason = reason + } + }) + } + + onRequestSent () { + if (this.handler.onRequestSent) { + this.handler.onRequestSent() + } + } + + onUpgrade (statusCode, headers, socket) { + if (this.handler.onUpgrade) { + this.handler.onUpgrade(statusCode, headers, socket) + } + } + + onConnect (abort) { + if (this.aborted) { + abort(this.reason) + } else { + this.abort = abort + } + } + + onBodySent (chunk) { + return this.handler.onBodySent(chunk) + } + + static [kRetryHandlerDefaultRetry] (err, { state, opts }, cb) { + const { statusCode, code, headers } = err + const { method, retryOptions } = opts + const { + maxRetries, + timeout, + maxTimeout, + timeoutFactor, + statusCodes, + errorCodes, + methods + } = retryOptions + let { counter, currentTimeout } = state + + currentTimeout = + currentTimeout != null && currentTimeout > 0 ? currentTimeout : timeout + + // Any code that is not a Undici's originated and allowed to retry + if ( + code && + code !== 'UND_ERR_REQ_RETRY' && + code !== 'UND_ERR_SOCKET' && + !errorCodes.includes(code) + ) { + cb(err) + return + } + + // If a set of method are provided and the current method is not in the list + if (Array.isArray(methods) && !methods.includes(method)) { + cb(err) + return + } + + // If a set of status code are provided and the current status code is not in the list + if ( + statusCode != null && + Array.isArray(statusCodes) && + !statusCodes.includes(statusCode) + ) { + cb(err) + return + } + + // If we reached the max number of retries + if (counter > maxRetries) { + cb(err) + return + } + + let retryAfterHeader = headers != null && headers['retry-after'] + if (retryAfterHeader) { + retryAfterHeader = Number(retryAfterHeader) + retryAfterHeader = isNaN(retryAfterHeader) + ? calculateRetryAfterHeader(retryAfterHeader) + : retryAfterHeader * 1e3 // Retry-After is in seconds + } + + const retryTimeout = + retryAfterHeader > 0 + ? Math.min(retryAfterHeader, maxTimeout) + : Math.min(currentTimeout * timeoutFactor ** counter, maxTimeout) + + state.currentTimeout = retryTimeout + + setTimeout(() => cb(null), retryTimeout) + } + + onHeaders (statusCode, rawHeaders, resume, statusMessage) { + const headers = parseHeaders(rawHeaders) + + this.retryCount += 1 + + if (statusCode >= 300) { + this.abort( + new RequestRetryError('Request failed', statusCode, { + headers, + count: this.retryCount + }) + ) + return false + } + + // Checkpoint for resume from where we left it + if (this.resume != null) { + this.resume = null + + if (statusCode !== 206) { + return true + } + + const contentRange = parseRangeHeader(headers['content-range']) + // If no content range + if (!contentRange) { + this.abort( + new RequestRetryError('Content-Range mismatch', statusCode, { + headers, + count: this.retryCount + }) + ) + return false + } + + // Let's start with a weak etag check + if (this.etag != null && this.etag !== headers.etag) { + this.abort( + new RequestRetryError('ETag mismatch', statusCode, { + headers, + count: this.retryCount + }) + ) + return false + } + + const { start, size, end = size } = contentRange + + assert(this.start === start, 'content-range mismatch') + assert(this.end == null || this.end === end, 'content-range mismatch') + + this.resume = resume + return true + } + + if (this.end == null) { + if (statusCode === 206) { + // First time we receive 206 + const range = parseRangeHeader(headers['content-range']) + + if (range == null) { + return this.handler.onHeaders( + statusCode, + rawHeaders, + resume, + statusMessage + ) + } + + const { start, size, end = size } = range + + assert( + start != null && Number.isFinite(start) && this.start !== start, + 'content-range mismatch' + ) + assert(Number.isFinite(start)) + assert( + end != null && Number.isFinite(end) && this.end !== end, + 'invalid content-length' + ) + + this.start = start + this.end = end + } + + // We make our best to checkpoint the body for further range headers + if (this.end == null) { + const contentLength = headers['content-length'] + this.end = contentLength != null ? Number(contentLength) : null + } + + assert(Number.isFinite(this.start)) + assert( + this.end == null || Number.isFinite(this.end), + 'invalid content-length' + ) + + this.resume = resume + this.etag = headers.etag != null ? headers.etag : null + + return this.handler.onHeaders( + statusCode, + rawHeaders, + resume, + statusMessage + ) + } + + const err = new RequestRetryError('Request failed', statusCode, { + headers, + count: this.retryCount + }) + + this.abort(err) + + return false + } + + onData (chunk) { + this.start += chunk.length + + return this.handler.onData(chunk) + } + + onComplete (rawTrailers) { + this.retryCount = 0 + return this.handler.onComplete(rawTrailers) + } + + onError (err) { + if (this.aborted || isDisturbed(this.opts.body)) { + return this.handler.onError(err) + } + + this.retryOpts.retry( + err, + { + state: { counter: this.retryCount++, currentTimeout: this.retryAfter }, + opts: { retryOptions: this.retryOpts, ...this.opts } + }, + onRetry.bind(this) + ) + + function onRetry (err) { + if (err != null || this.aborted || isDisturbed(this.opts.body)) { + return this.handler.onError(err) + } + + if (this.start !== 0) { + this.opts = { + ...this.opts, + headers: { + ...this.opts.headers, + range: `bytes=${this.start}-${this.end ?? ''}` + } + } + } + + try { + this.dispatch(this.opts, this) + } catch (err) { + this.handler.onError(err) + } + } + } +} + +module.exports = RetryHandler + + +/***/ }), + +/***/ 5260: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const RedirectHandler = __nccwpck_require__(7491) + +function createRedirectInterceptor ({ maxRedirections: defaultMaxRedirections }) { + return (dispatch) => { + return function Intercept (opts, handler) { + const { maxRedirections = defaultMaxRedirections } = opts + + if (!maxRedirections) { + return dispatch(opts, handler) + } + + const redirectHandler = new RedirectHandler(dispatch, maxRedirections, opts, handler) + opts = { ...opts, maxRedirections: 0 } // Stop sub dispatcher from also redirecting. + return dispatch(opts, redirectHandler) + } + } +} + +module.exports = createRedirectInterceptor + + +/***/ }), + +/***/ 5153: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.SPECIAL_HEADERS = exports.HEADER_STATE = exports.MINOR = exports.MAJOR = exports.CONNECTION_TOKEN_CHARS = exports.HEADER_CHARS = exports.TOKEN = exports.STRICT_TOKEN = exports.HEX = exports.URL_CHAR = exports.STRICT_URL_CHAR = exports.USERINFO_CHARS = exports.MARK = exports.ALPHANUM = exports.NUM = exports.HEX_MAP = exports.NUM_MAP = exports.ALPHA = exports.FINISH = exports.H_METHOD_MAP = exports.METHOD_MAP = exports.METHODS_RTSP = exports.METHODS_ICE = exports.METHODS_HTTP = exports.METHODS = exports.LENIENT_FLAGS = exports.FLAGS = exports.TYPE = exports.ERROR = void 0; +const utils_1 = __nccwpck_require__(3537); +// C headers +var ERROR; +(function (ERROR) { + ERROR[ERROR["OK"] = 0] = "OK"; + ERROR[ERROR["INTERNAL"] = 1] = "INTERNAL"; + ERROR[ERROR["STRICT"] = 2] = "STRICT"; + ERROR[ERROR["LF_EXPECTED"] = 3] = "LF_EXPECTED"; + ERROR[ERROR["UNEXPECTED_CONTENT_LENGTH"] = 4] = "UNEXPECTED_CONTENT_LENGTH"; + ERROR[ERROR["CLOSED_CONNECTION"] = 5] = "CLOSED_CONNECTION"; + ERROR[ERROR["INVALID_METHOD"] = 6] = "INVALID_METHOD"; + ERROR[ERROR["INVALID_URL"] = 7] = "INVALID_URL"; + ERROR[ERROR["INVALID_CONSTANT"] = 8] = "INVALID_CONSTANT"; + ERROR[ERROR["INVALID_VERSION"] = 9] = "INVALID_VERSION"; + ERROR[ERROR["INVALID_HEADER_TOKEN"] = 10] = "INVALID_HEADER_TOKEN"; + ERROR[ERROR["INVALID_CONTENT_LENGTH"] = 11] = "INVALID_CONTENT_LENGTH"; + ERROR[ERROR["INVALID_CHUNK_SIZE"] = 12] = "INVALID_CHUNK_SIZE"; + ERROR[ERROR["INVALID_STATUS"] = 13] = "INVALID_STATUS"; + ERROR[ERROR["INVALID_EOF_STATE"] = 14] = "INVALID_EOF_STATE"; + ERROR[ERROR["INVALID_TRANSFER_ENCODING"] = 15] = "INVALID_TRANSFER_ENCODING"; + ERROR[ERROR["CB_MESSAGE_BEGIN"] = 16] = "CB_MESSAGE_BEGIN"; + ERROR[ERROR["CB_HEADERS_COMPLETE"] = 17] = "CB_HEADERS_COMPLETE"; + ERROR[ERROR["CB_MESSAGE_COMPLETE"] = 18] = "CB_MESSAGE_COMPLETE"; + ERROR[ERROR["CB_CHUNK_HEADER"] = 19] = "CB_CHUNK_HEADER"; + ERROR[ERROR["CB_CHUNK_COMPLETE"] = 20] = "CB_CHUNK_COMPLETE"; + ERROR[ERROR["PAUSED"] = 21] = "PAUSED"; + ERROR[ERROR["PAUSED_UPGRADE"] = 22] = "PAUSED_UPGRADE"; + ERROR[ERROR["PAUSED_H2_UPGRADE"] = 23] = "PAUSED_H2_UPGRADE"; + ERROR[ERROR["USER"] = 24] = "USER"; +})(ERROR = exports.ERROR || (exports.ERROR = {})); +var TYPE; +(function (TYPE) { + TYPE[TYPE["BOTH"] = 0] = "BOTH"; + TYPE[TYPE["REQUEST"] = 1] = "REQUEST"; + TYPE[TYPE["RESPONSE"] = 2] = "RESPONSE"; +})(TYPE = exports.TYPE || (exports.TYPE = {})); +var FLAGS; +(function (FLAGS) { + FLAGS[FLAGS["CONNECTION_KEEP_ALIVE"] = 1] = "CONNECTION_KEEP_ALIVE"; + FLAGS[FLAGS["CONNECTION_CLOSE"] = 2] = "CONNECTION_CLOSE"; + FLAGS[FLAGS["CONNECTION_UPGRADE"] = 4] = "CONNECTION_UPGRADE"; + FLAGS[FLAGS["CHUNKED"] = 8] = "CHUNKED"; + FLAGS[FLAGS["UPGRADE"] = 16] = "UPGRADE"; + FLAGS[FLAGS["CONTENT_LENGTH"] = 32] = "CONTENT_LENGTH"; + FLAGS[FLAGS["SKIPBODY"] = 64] = "SKIPBODY"; + FLAGS[FLAGS["TRAILING"] = 128] = "TRAILING"; + // 1 << 8 is unused + FLAGS[FLAGS["TRANSFER_ENCODING"] = 512] = "TRANSFER_ENCODING"; +})(FLAGS = exports.FLAGS || (exports.FLAGS = {})); +var LENIENT_FLAGS; +(function (LENIENT_FLAGS) { + LENIENT_FLAGS[LENIENT_FLAGS["HEADERS"] = 1] = "HEADERS"; + LENIENT_FLAGS[LENIENT_FLAGS["CHUNKED_LENGTH"] = 2] = "CHUNKED_LENGTH"; + LENIENT_FLAGS[LENIENT_FLAGS["KEEP_ALIVE"] = 4] = "KEEP_ALIVE"; +})(LENIENT_FLAGS = exports.LENIENT_FLAGS || (exports.LENIENT_FLAGS = {})); +var METHODS; +(function (METHODS) { + METHODS[METHODS["DELETE"] = 0] = "DELETE"; + METHODS[METHODS["GET"] = 1] = "GET"; + METHODS[METHODS["HEAD"] = 2] = "HEAD"; + METHODS[METHODS["POST"] = 3] = "POST"; + METHODS[METHODS["PUT"] = 4] = "PUT"; + /* pathological */ + METHODS[METHODS["CONNECT"] = 5] = "CONNECT"; + METHODS[METHODS["OPTIONS"] = 6] = "OPTIONS"; + METHODS[METHODS["TRACE"] = 7] = "TRACE"; + /* WebDAV */ + METHODS[METHODS["COPY"] = 8] = "COPY"; + METHODS[METHODS["LOCK"] = 9] = "LOCK"; + METHODS[METHODS["MKCOL"] = 10] = "MKCOL"; + METHODS[METHODS["MOVE"] = 11] = "MOVE"; + METHODS[METHODS["PROPFIND"] = 12] = "PROPFIND"; + METHODS[METHODS["PROPPATCH"] = 13] = "PROPPATCH"; + METHODS[METHODS["SEARCH"] = 14] = "SEARCH"; + METHODS[METHODS["UNLOCK"] = 15] = "UNLOCK"; + METHODS[METHODS["BIND"] = 16] = "BIND"; + METHODS[METHODS["REBIND"] = 17] = "REBIND"; + METHODS[METHODS["UNBIND"] = 18] = "UNBIND"; + METHODS[METHODS["ACL"] = 19] = "ACL"; + /* subversion */ + METHODS[METHODS["REPORT"] = 20] = "REPORT"; + METHODS[METHODS["MKACTIVITY"] = 21] = "MKACTIVITY"; + METHODS[METHODS["CHECKOUT"] = 22] = "CHECKOUT"; + METHODS[METHODS["MERGE"] = 23] = "MERGE"; + /* upnp */ + METHODS[METHODS["M-SEARCH"] = 24] = "M-SEARCH"; + METHODS[METHODS["NOTIFY"] = 25] = "NOTIFY"; + METHODS[METHODS["SUBSCRIBE"] = 26] = "SUBSCRIBE"; + METHODS[METHODS["UNSUBSCRIBE"] = 27] = "UNSUBSCRIBE"; + /* RFC-5789 */ + METHODS[METHODS["PATCH"] = 28] = "PATCH"; + METHODS[METHODS["PURGE"] = 29] = "PURGE"; + /* CalDAV */ + METHODS[METHODS["MKCALENDAR"] = 30] = "MKCALENDAR"; + /* RFC-2068, section 19.6.1.2 */ + METHODS[METHODS["LINK"] = 31] = "LINK"; + METHODS[METHODS["UNLINK"] = 32] = "UNLINK"; + /* icecast */ + METHODS[METHODS["SOURCE"] = 33] = "SOURCE"; + /* RFC-7540, section 11.6 */ + METHODS[METHODS["PRI"] = 34] = "PRI"; + /* RFC-2326 RTSP */ + METHODS[METHODS["DESCRIBE"] = 35] = "DESCRIBE"; + METHODS[METHODS["ANNOUNCE"] = 36] = "ANNOUNCE"; + METHODS[METHODS["SETUP"] = 37] = "SETUP"; + METHODS[METHODS["PLAY"] = 38] = "PLAY"; + METHODS[METHODS["PAUSE"] = 39] = "PAUSE"; + METHODS[METHODS["TEARDOWN"] = 40] = "TEARDOWN"; + METHODS[METHODS["GET_PARAMETER"] = 41] = "GET_PARAMETER"; + METHODS[METHODS["SET_PARAMETER"] = 42] = "SET_PARAMETER"; + METHODS[METHODS["REDIRECT"] = 43] = "REDIRECT"; + METHODS[METHODS["RECORD"] = 44] = "RECORD"; + /* RAOP */ + METHODS[METHODS["FLUSH"] = 45] = "FLUSH"; +})(METHODS = exports.METHODS || (exports.METHODS = {})); +exports.METHODS_HTTP = [ + METHODS.DELETE, + METHODS.GET, + METHODS.HEAD, + METHODS.POST, + METHODS.PUT, + METHODS.CONNECT, + METHODS.OPTIONS, + METHODS.TRACE, + METHODS.COPY, + METHODS.LOCK, + METHODS.MKCOL, + METHODS.MOVE, + METHODS.PROPFIND, + METHODS.PROPPATCH, + METHODS.SEARCH, + METHODS.UNLOCK, + METHODS.BIND, + METHODS.REBIND, + METHODS.UNBIND, + METHODS.ACL, + METHODS.REPORT, + METHODS.MKACTIVITY, + METHODS.CHECKOUT, + METHODS.MERGE, + METHODS['M-SEARCH'], + METHODS.NOTIFY, + METHODS.SUBSCRIBE, + METHODS.UNSUBSCRIBE, + METHODS.PATCH, + METHODS.PURGE, + METHODS.MKCALENDAR, + METHODS.LINK, + METHODS.UNLINK, + METHODS.PRI, + // TODO(indutny): should we allow it with HTTP? + METHODS.SOURCE, +]; +exports.METHODS_ICE = [ + METHODS.SOURCE, +]; +exports.METHODS_RTSP = [ + METHODS.OPTIONS, + METHODS.DESCRIBE, + METHODS.ANNOUNCE, + METHODS.SETUP, + METHODS.PLAY, + METHODS.PAUSE, + METHODS.TEARDOWN, + METHODS.GET_PARAMETER, + METHODS.SET_PARAMETER, + METHODS.REDIRECT, + METHODS.RECORD, + METHODS.FLUSH, + // For AirPlay + METHODS.GET, + METHODS.POST, +]; +exports.METHOD_MAP = utils_1.enumToMap(METHODS); +exports.H_METHOD_MAP = {}; +Object.keys(exports.METHOD_MAP).forEach((key) => { + if (/^H/.test(key)) { + exports.H_METHOD_MAP[key] = exports.METHOD_MAP[key]; + } +}); +var FINISH; +(function (FINISH) { + FINISH[FINISH["SAFE"] = 0] = "SAFE"; + FINISH[FINISH["SAFE_WITH_CB"] = 1] = "SAFE_WITH_CB"; + FINISH[FINISH["UNSAFE"] = 2] = "UNSAFE"; +})(FINISH = exports.FINISH || (exports.FINISH = {})); +exports.ALPHA = []; +for (let i = 'A'.charCodeAt(0); i <= 'Z'.charCodeAt(0); i++) { + // Upper case + exports.ALPHA.push(String.fromCharCode(i)); + // Lower case + exports.ALPHA.push(String.fromCharCode(i + 0x20)); +} +exports.NUM_MAP = { + 0: 0, 1: 1, 2: 2, 3: 3, 4: 4, + 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, +}; +exports.HEX_MAP = { + 0: 0, 1: 1, 2: 2, 3: 3, 4: 4, + 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, + A: 0XA, B: 0XB, C: 0XC, D: 0XD, E: 0XE, F: 0XF, + a: 0xa, b: 0xb, c: 0xc, d: 0xd, e: 0xe, f: 0xf, +}; +exports.NUM = [ + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', +]; +exports.ALPHANUM = exports.ALPHA.concat(exports.NUM); +exports.MARK = ['-', '_', '.', '!', '~', '*', '\'', '(', ')']; +exports.USERINFO_CHARS = exports.ALPHANUM + .concat(exports.MARK) + .concat(['%', ';', ':', '&', '=', '+', '$', ',']); +// TODO(indutny): use RFC +exports.STRICT_URL_CHAR = [ + '!', '"', '$', '%', '&', '\'', + '(', ')', '*', '+', ',', '-', '.', '/', + ':', ';', '<', '=', '>', + '@', '[', '\\', ']', '^', '_', + '`', + '{', '|', '}', '~', +].concat(exports.ALPHANUM); +exports.URL_CHAR = exports.STRICT_URL_CHAR + .concat(['\t', '\f']); +// All characters with 0x80 bit set to 1 +for (let i = 0x80; i <= 0xff; i++) { + exports.URL_CHAR.push(i); +} +exports.HEX = exports.NUM.concat(['a', 'b', 'c', 'd', 'e', 'f', 'A', 'B', 'C', 'D', 'E', 'F']); +/* Tokens as defined by rfc 2616. Also lowercases them. + * token = 1* + * separators = "(" | ")" | "<" | ">" | "@" + * | "," | ";" | ":" | "\" | <"> + * | "/" | "[" | "]" | "?" | "=" + * | "{" | "}" | SP | HT + */ +exports.STRICT_TOKEN = [ + '!', '#', '$', '%', '&', '\'', + '*', '+', '-', '.', + '^', '_', '`', + '|', '~', +].concat(exports.ALPHANUM); +exports.TOKEN = exports.STRICT_TOKEN.concat([' ']); +/* + * Verify that a char is a valid visible (printable) US-ASCII + * character or %x80-FF + */ +exports.HEADER_CHARS = ['\t']; +for (let i = 32; i <= 255; i++) { + if (i !== 127) { + exports.HEADER_CHARS.push(i); + } +} +// ',' = \x44 +exports.CONNECTION_TOKEN_CHARS = exports.HEADER_CHARS.filter((c) => c !== 44); +exports.MAJOR = exports.NUM_MAP; +exports.MINOR = exports.MAJOR; +var HEADER_STATE; +(function (HEADER_STATE) { + HEADER_STATE[HEADER_STATE["GENERAL"] = 0] = "GENERAL"; + HEADER_STATE[HEADER_STATE["CONNECTION"] = 1] = "CONNECTION"; + HEADER_STATE[HEADER_STATE["CONTENT_LENGTH"] = 2] = "CONTENT_LENGTH"; + HEADER_STATE[HEADER_STATE["TRANSFER_ENCODING"] = 3] = "TRANSFER_ENCODING"; + HEADER_STATE[HEADER_STATE["UPGRADE"] = 4] = "UPGRADE"; + HEADER_STATE[HEADER_STATE["CONNECTION_KEEP_ALIVE"] = 5] = "CONNECTION_KEEP_ALIVE"; + HEADER_STATE[HEADER_STATE["CONNECTION_CLOSE"] = 6] = "CONNECTION_CLOSE"; + HEADER_STATE[HEADER_STATE["CONNECTION_UPGRADE"] = 7] = "CONNECTION_UPGRADE"; + HEADER_STATE[HEADER_STATE["TRANSFER_ENCODING_CHUNKED"] = 8] = "TRANSFER_ENCODING_CHUNKED"; +})(HEADER_STATE = exports.HEADER_STATE || (exports.HEADER_STATE = {})); +exports.SPECIAL_HEADERS = { + 'connection': HEADER_STATE.CONNECTION, + 'content-length': HEADER_STATE.CONTENT_LENGTH, + 'proxy-connection': HEADER_STATE.CONNECTION, + 'transfer-encoding': HEADER_STATE.TRANSFER_ENCODING, + 'upgrade': HEADER_STATE.UPGRADE, +}; +//# sourceMappingURL=constants.js.map + +/***/ }), + +/***/ 4650: +/***/ ((module) => { + +module.exports = 'AGFzbQEAAAABMAhgAX8Bf2ADf39/AX9gBH9/f38Bf2AAAGADf39/AGABfwBgAn9/AGAGf39/f39/AALLAQgDZW52GHdhc21fb25faGVhZGVyc19jb21wbGV0ZQACA2VudhV3YXNtX29uX21lc3NhZ2VfYmVnaW4AAANlbnYLd2FzbV9vbl91cmwAAQNlbnYOd2FzbV9vbl9zdGF0dXMAAQNlbnYUd2FzbV9vbl9oZWFkZXJfZmllbGQAAQNlbnYUd2FzbV9vbl9oZWFkZXJfdmFsdWUAAQNlbnYMd2FzbV9vbl9ib2R5AAEDZW52GHdhc21fb25fbWVzc2FnZV9jb21wbGV0ZQAAA0ZFAwMEAAAFAAAAAAAABQEFAAUFBQAABgAAAAAGBgYGAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAAABAQcAAAUFAwABBAUBcAESEgUDAQACBggBfwFBgNQECwfRBSIGbWVtb3J5AgALX2luaXRpYWxpemUACRlfX2luZGlyZWN0X2Z1bmN0aW9uX3RhYmxlAQALbGxodHRwX2luaXQAChhsbGh0dHBfc2hvdWxkX2tlZXBfYWxpdmUAQQxsbGh0dHBfYWxsb2MADAZtYWxsb2MARgtsbGh0dHBfZnJlZQANBGZyZWUASA9sbGh0dHBfZ2V0X3R5cGUADhVsbGh0dHBfZ2V0X2h0dHBfbWFqb3IADxVsbGh0dHBfZ2V0X2h0dHBfbWlub3IAEBFsbGh0dHBfZ2V0X21ldGhvZAARFmxsaHR0cF9nZXRfc3RhdHVzX2NvZGUAEhJsbGh0dHBfZ2V0X3VwZ3JhZGUAEwxsbGh0dHBfcmVzZXQAFA5sbGh0dHBfZXhlY3V0ZQAVFGxsaHR0cF9zZXR0aW5nc19pbml0ABYNbGxodHRwX2ZpbmlzaAAXDGxsaHR0cF9wYXVzZQAYDWxsaHR0cF9yZXN1bWUAGRtsbGh0dHBfcmVzdW1lX2FmdGVyX3VwZ3JhZGUAGhBsbGh0dHBfZ2V0X2Vycm5vABsXbGxodHRwX2dldF9lcnJvcl9yZWFzb24AHBdsbGh0dHBfc2V0X2Vycm9yX3JlYXNvbgAdFGxsaHR0cF9nZXRfZXJyb3JfcG9zAB4RbGxodHRwX2Vycm5vX25hbWUAHxJsbGh0dHBfbWV0aG9kX25hbWUAIBJsbGh0dHBfc3RhdHVzX25hbWUAIRpsbGh0dHBfc2V0X2xlbmllbnRfaGVhZGVycwAiIWxsaHR0cF9zZXRfbGVuaWVudF9jaHVua2VkX2xlbmd0aAAjHWxsaHR0cF9zZXRfbGVuaWVudF9rZWVwX2FsaXZlACQkbGxodHRwX3NldF9sZW5pZW50X3RyYW5zZmVyX2VuY29kaW5nACUYbGxodHRwX21lc3NhZ2VfbmVlZHNfZW9mAD8JFwEAQQELEQECAwQFCwYHNTk3MS8tJyspCsLgAkUCAAsIABCIgICAAAsZACAAEMKAgIAAGiAAIAI2AjggACABOgAoCxwAIAAgAC8BMiAALQAuIAAQwYCAgAAQgICAgAALKgEBf0HAABDGgICAACIBEMKAgIAAGiABQYCIgIAANgI4IAEgADoAKCABCwoAIAAQyICAgAALBwAgAC0AKAsHACAALQAqCwcAIAAtACsLBwAgAC0AKQsHACAALwEyCwcAIAAtAC4LRQEEfyAAKAIYIQEgAC0ALSECIAAtACghAyAAKAI4IQQgABDCgICAABogACAENgI4IAAgAzoAKCAAIAI6AC0gACABNgIYCxEAIAAgASABIAJqEMOAgIAACxAAIABBAEHcABDMgICAABoLZwEBf0EAIQECQCAAKAIMDQACQAJAAkACQCAALQAvDgMBAAMCCyAAKAI4IgFFDQAgASgCLCIBRQ0AIAAgARGAgICAAAAiAQ0DC0EADwsQyoCAgAAACyAAQcOWgIAANgIQQQ4hAQsgAQseAAJAIAAoAgwNACAAQdGbgIAANgIQIABBFTYCDAsLFgACQCAAKAIMQRVHDQAgAEEANgIMCwsWAAJAIAAoAgxBFkcNACAAQQA2AgwLCwcAIAAoAgwLBwAgACgCEAsJACAAIAE2AhALBwAgACgCFAsiAAJAIABBJEkNABDKgICAAAALIABBAnRBoLOAgABqKAIACyIAAkAgAEEuSQ0AEMqAgIAAAAsgAEECdEGwtICAAGooAgAL7gsBAX9B66iAgAAhAQJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAIABBnH9qDvQDY2IAAWFhYWFhYQIDBAVhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhBgcICQoLDA0OD2FhYWFhEGFhYWFhYWFhYWFhEWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYRITFBUWFxgZGhthYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhHB0eHyAhIiMkJSYnKCkqKywtLi8wMTIzNDU2YTc4OTphYWFhYWFhYTthYWE8YWFhYT0+P2FhYWFhYWFhQGFhQWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYUJDREVGR0hJSktMTU5PUFFSU2FhYWFhYWFhVFVWV1hZWlthXF1hYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFeYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhX2BhC0Hhp4CAAA8LQaShgIAADwtBy6yAgAAPC0H+sYCAAA8LQcCkgIAADwtBq6SAgAAPC0GNqICAAA8LQeKmgIAADwtBgLCAgAAPC0G5r4CAAA8LQdekgIAADwtB75+AgAAPC0Hhn4CAAA8LQfqfgIAADwtB8qCAgAAPC0Gor4CAAA8LQa6ygIAADwtBiLCAgAAPC0Hsp4CAAA8LQYKigIAADwtBjp2AgAAPC0HQroCAAA8LQcqjgIAADwtBxbKAgAAPC0HfnICAAA8LQdKcgIAADwtBxKCAgAAPC0HXoICAAA8LQaKfgIAADwtB7a6AgAAPC0GrsICAAA8LQdSlgIAADwtBzK6AgAAPC0H6roCAAA8LQfyrgIAADwtB0rCAgAAPC0HxnYCAAA8LQbuggIAADwtB96uAgAAPC0GQsYCAAA8LQdexgIAADwtBoq2AgAAPC0HUp4CAAA8LQeCrgIAADwtBn6yAgAAPC0HrsYCAAA8LQdWfgIAADwtByrGAgAAPC0HepYCAAA8LQdSegIAADwtB9JyAgAAPC0GnsoCAAA8LQbGdgIAADwtBoJ2AgAAPC0G5sYCAAA8LQbywgIAADwtBkqGAgAAPC0GzpoCAAA8LQemsgIAADwtBrJ6AgAAPC0HUq4CAAA8LQfemgIAADwtBgKaAgAAPC0GwoYCAAA8LQf6egIAADwtBjaOAgAAPC0GJrYCAAA8LQfeigIAADwtBoLGAgAAPC0Gun4CAAA8LQcalgIAADwtB6J6AgAAPC0GTooCAAA8LQcKvgIAADwtBw52AgAAPC0GLrICAAA8LQeGdgIAADwtBja+AgAAPC0HqoYCAAA8LQbStgIAADwtB0q+AgAAPC0HfsoCAAA8LQdKygIAADwtB8LCAgAAPC0GpooCAAA8LQfmjgIAADwtBmZ6AgAAPC0G1rICAAA8LQZuwgIAADwtBkrKAgAAPC0G2q4CAAA8LQcKigIAADwtB+LKAgAAPC0GepYCAAA8LQdCigIAADwtBup6AgAAPC0GBnoCAAA8LEMqAgIAAAAtB1qGAgAAhAQsgAQsWACAAIAAtAC1B/gFxIAFBAEdyOgAtCxkAIAAgAC0ALUH9AXEgAUEAR0EBdHI6AC0LGQAgACAALQAtQfsBcSABQQBHQQJ0cjoALQsZACAAIAAtAC1B9wFxIAFBAEdBA3RyOgAtCy4BAn9BACEDAkAgACgCOCIERQ0AIAQoAgAiBEUNACAAIAQRgICAgAAAIQMLIAMLSQECf0EAIQMCQCAAKAI4IgRFDQAgBCgCBCIERQ0AIAAgASACIAFrIAQRgYCAgAAAIgNBf0cNACAAQcaRgIAANgIQQRghAwsgAwsuAQJ/QQAhAwJAIAAoAjgiBEUNACAEKAIwIgRFDQAgACAEEYCAgIAAACEDCyADC0kBAn9BACEDAkAgACgCOCIERQ0AIAQoAggiBEUNACAAIAEgAiABayAEEYGAgIAAACIDQX9HDQAgAEH2ioCAADYCEEEYIQMLIAMLLgECf0EAIQMCQCAAKAI4IgRFDQAgBCgCNCIERQ0AIAAgBBGAgICAAAAhAwsgAwtJAQJ/QQAhAwJAIAAoAjgiBEUNACAEKAIMIgRFDQAgACABIAIgAWsgBBGBgICAAAAiA0F/Rw0AIABB7ZqAgAA2AhBBGCEDCyADCy4BAn9BACEDAkAgACgCOCIERQ0AIAQoAjgiBEUNACAAIAQRgICAgAAAIQMLIAMLSQECf0EAIQMCQCAAKAI4IgRFDQAgBCgCECIERQ0AIAAgASACIAFrIAQRgYCAgAAAIgNBf0cNACAAQZWQgIAANgIQQRghAwsgAwsuAQJ/QQAhAwJAIAAoAjgiBEUNACAEKAI8IgRFDQAgACAEEYCAgIAAACEDCyADC0kBAn9BACEDAkAgACgCOCIERQ0AIAQoAhQiBEUNACAAIAEgAiABayAEEYGAgIAAACIDQX9HDQAgAEGqm4CAADYCEEEYIQMLIAMLLgECf0EAIQMCQCAAKAI4IgRFDQAgBCgCQCIERQ0AIAAgBBGAgICAAAAhAwsgAwtJAQJ/QQAhAwJAIAAoAjgiBEUNACAEKAIYIgRFDQAgACABIAIgAWsgBBGBgICAAAAiA0F/Rw0AIABB7ZOAgAA2AhBBGCEDCyADCy4BAn9BACEDAkAgACgCOCIERQ0AIAQoAkQiBEUNACAAIAQRgICAgAAAIQMLIAMLLgECf0EAIQMCQCAAKAI4IgRFDQAgBCgCJCIERQ0AIAAgBBGAgICAAAAhAwsgAwsuAQJ/QQAhAwJAIAAoAjgiBEUNACAEKAIsIgRFDQAgACAEEYCAgIAAACEDCyADC0kBAn9BACEDAkAgACgCOCIERQ0AIAQoAigiBEUNACAAIAEgAiABayAEEYGAgIAAACIDQX9HDQAgAEH2iICAADYCEEEYIQMLIAMLLgECf0EAIQMCQCAAKAI4IgRFDQAgBCgCUCIERQ0AIAAgBBGAgICAAAAhAwsgAwtJAQJ/QQAhAwJAIAAoAjgiBEUNACAEKAIcIgRFDQAgACABIAIgAWsgBBGBgICAAAAiA0F/Rw0AIABBwpmAgAA2AhBBGCEDCyADCy4BAn9BACEDAkAgACgCOCIERQ0AIAQoAkgiBEUNACAAIAQRgICAgAAAIQMLIAMLSQECf0EAIQMCQCAAKAI4IgRFDQAgBCgCICIERQ0AIAAgASACIAFrIAQRgYCAgAAAIgNBf0cNACAAQZSUgIAANgIQQRghAwsgAwsuAQJ/QQAhAwJAIAAoAjgiBEUNACAEKAJMIgRFDQAgACAEEYCAgIAAACEDCyADCy4BAn9BACEDAkAgACgCOCIERQ0AIAQoAlQiBEUNACAAIAQRgICAgAAAIQMLIAMLLgECf0EAIQMCQCAAKAI4IgRFDQAgBCgCWCIERQ0AIAAgBBGAgICAAAAhAwsgAwtFAQF/AkACQCAALwEwQRRxQRRHDQBBASEDIAAtAChBAUYNASAALwEyQeUARiEDDAELIAAtAClBBUYhAwsgACADOgAuQQAL/gEBA39BASEDAkAgAC8BMCIEQQhxDQAgACkDIEIAUiEDCwJAAkAgAC0ALkUNAEEBIQUgAC0AKUEFRg0BQQEhBSAEQcAAcUUgA3FBAUcNAQtBACEFIARBwABxDQBBAiEFIARB//8DcSIDQQhxDQACQCADQYAEcUUNAAJAIAAtAChBAUcNACAALQAtQQpxDQBBBQ8LQQQPCwJAIANBIHENAAJAIAAtAChBAUYNACAALwEyQf//A3EiAEGcf2pB5ABJDQAgAEHMAUYNACAAQbACRg0AQQQhBSAEQShxRQ0CIANBiARxQYAERg0CC0EADwtBAEEDIAApAyBQGyEFCyAFC2IBAn9BACEBAkAgAC0AKEEBRg0AIAAvATJB//8DcSICQZx/akHkAEkNACACQcwBRg0AIAJBsAJGDQAgAC8BMCIAQcAAcQ0AQQEhASAAQYgEcUGABEYNACAAQShxRSEBCyABC6cBAQN/AkACQAJAIAAtACpFDQAgAC0AK0UNAEEAIQMgAC8BMCIEQQJxRQ0BDAILQQAhAyAALwEwIgRBAXFFDQELQQEhAyAALQAoQQFGDQAgAC8BMkH//wNxIgVBnH9qQeQASQ0AIAVBzAFGDQAgBUGwAkYNACAEQcAAcQ0AQQAhAyAEQYgEcUGABEYNACAEQShxQQBHIQMLIABBADsBMCAAQQA6AC8gAwuZAQECfwJAAkACQCAALQAqRQ0AIAAtACtFDQBBACEBIAAvATAiAkECcUUNAQwCC0EAIQEgAC8BMCICQQFxRQ0BC0EBIQEgAC0AKEEBRg0AIAAvATJB//8DcSIAQZx/akHkAEkNACAAQcwBRg0AIABBsAJGDQAgAkHAAHENAEEAIQEgAkGIBHFBgARGDQAgAkEocUEARyEBCyABC1kAIABBGGpCADcDACAAQgA3AwAgAEE4akIANwMAIABBMGpCADcDACAAQShqQgA3AwAgAEEgakIANwMAIABBEGpCADcDACAAQQhqQgA3AwAgAEHdATYCHEEAC3sBAX8CQCAAKAIMIgMNAAJAIAAoAgRFDQAgACABNgIECwJAIAAgASACEMSAgIAAIgMNACAAKAIMDwsgACADNgIcQQAhAyAAKAIEIgFFDQAgACABIAIgACgCCBGBgICAAAAiAUUNACAAIAI2AhQgACABNgIMIAEhAwsgAwvk8wEDDn8DfgR/I4CAgIAAQRBrIgMkgICAgAAgASEEIAEhBSABIQYgASEHIAEhCCABIQkgASEKIAEhCyABIQwgASENIAEhDiABIQ8CQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAgACgCHCIQQX9qDt0B2gEB2QECAwQFBgcICQoLDA0O2AEPENcBERLWARMUFRYXGBkaG+AB3wEcHR7VAR8gISIjJCXUASYnKCkqKyzTAdIBLS7RAdABLzAxMjM0NTY3ODk6Ozw9Pj9AQUJDREVG2wFHSElKzwHOAUvNAUzMAU1OT1BRUlNUVVZXWFlaW1xdXl9gYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXp7fH1+f4ABgQGCAYMBhAGFAYYBhwGIAYkBigGLAYwBjQGOAY8BkAGRAZIBkwGUAZUBlgGXAZgBmQGaAZsBnAGdAZ4BnwGgAaEBogGjAaQBpQGmAacBqAGpAaoBqwGsAa0BrgGvAbABsQGyAbMBtAG1AbYBtwHLAcoBuAHJAbkByAG6AbsBvAG9Ab4BvwHAAcEBwgHDAcQBxQHGAQDcAQtBACEQDMYBC0EOIRAMxQELQQ0hEAzEAQtBDyEQDMMBC0EQIRAMwgELQRMhEAzBAQtBFCEQDMABC0EVIRAMvwELQRYhEAy+AQtBFyEQDL0BC0EYIRAMvAELQRkhEAy7AQtBGiEQDLoBC0EbIRAMuQELQRwhEAy4AQtBCCEQDLcBC0EdIRAMtgELQSAhEAy1AQtBHyEQDLQBC0EHIRAMswELQSEhEAyyAQtBIiEQDLEBC0EeIRAMsAELQSMhEAyvAQtBEiEQDK4BC0ERIRAMrQELQSQhEAysAQtBJSEQDKsBC0EmIRAMqgELQSchEAypAQtBwwEhEAyoAQtBKSEQDKcBC0ErIRAMpgELQSwhEAylAQtBLSEQDKQBC0EuIRAMowELQS8hEAyiAQtBxAEhEAyhAQtBMCEQDKABC0E0IRAMnwELQQwhEAyeAQtBMSEQDJ0BC0EyIRAMnAELQTMhEAybAQtBOSEQDJoBC0E1IRAMmQELQcUBIRAMmAELQQshEAyXAQtBOiEQDJYBC0E2IRAMlQELQQohEAyUAQtBNyEQDJMBC0E4IRAMkgELQTwhEAyRAQtBOyEQDJABC0E9IRAMjwELQQkhEAyOAQtBKCEQDI0BC0E+IRAMjAELQT8hEAyLAQtBwAAhEAyKAQtBwQAhEAyJAQtBwgAhEAyIAQtBwwAhEAyHAQtBxAAhEAyGAQtBxQAhEAyFAQtBxgAhEAyEAQtBKiEQDIMBC0HHACEQDIIBC0HIACEQDIEBC0HJACEQDIABC0HKACEQDH8LQcsAIRAMfgtBzQAhEAx9C0HMACEQDHwLQc4AIRAMewtBzwAhEAx6C0HQACEQDHkLQdEAIRAMeAtB0gAhEAx3C0HTACEQDHYLQdQAIRAMdQtB1gAhEAx0C0HVACEQDHMLQQYhEAxyC0HXACEQDHELQQUhEAxwC0HYACEQDG8LQQQhEAxuC0HZACEQDG0LQdoAIRAMbAtB2wAhEAxrC0HcACEQDGoLQQMhEAxpC0HdACEQDGgLQd4AIRAMZwtB3wAhEAxmC0HhACEQDGULQeAAIRAMZAtB4gAhEAxjC0HjACEQDGILQQIhEAxhC0HkACEQDGALQeUAIRAMXwtB5gAhEAxeC0HnACEQDF0LQegAIRAMXAtB6QAhEAxbC0HqACEQDFoLQesAIRAMWQtB7AAhEAxYC0HtACEQDFcLQe4AIRAMVgtB7wAhEAxVC0HwACEQDFQLQfEAIRAMUwtB8gAhEAxSC0HzACEQDFELQfQAIRAMUAtB9QAhEAxPC0H2ACEQDE4LQfcAIRAMTQtB+AAhEAxMC0H5ACEQDEsLQfoAIRAMSgtB+wAhEAxJC0H8ACEQDEgLQf0AIRAMRwtB/gAhEAxGC0H/ACEQDEULQYABIRAMRAtBgQEhEAxDC0GCASEQDEILQYMBIRAMQQtBhAEhEAxAC0GFASEQDD8LQYYBIRAMPgtBhwEhEAw9C0GIASEQDDwLQYkBIRAMOwtBigEhEAw6C0GLASEQDDkLQYwBIRAMOAtBjQEhEAw3C0GOASEQDDYLQY8BIRAMNQtBkAEhEAw0C0GRASEQDDMLQZIBIRAMMgtBkwEhEAwxC0GUASEQDDALQZUBIRAMLwtBlgEhEAwuC0GXASEQDC0LQZgBIRAMLAtBmQEhEAwrC0GaASEQDCoLQZsBIRAMKQtBnAEhEAwoC0GdASEQDCcLQZ4BIRAMJgtBnwEhEAwlC0GgASEQDCQLQaEBIRAMIwtBogEhEAwiC0GjASEQDCELQaQBIRAMIAtBpQEhEAwfC0GmASEQDB4LQacBIRAMHQtBqAEhEAwcC0GpASEQDBsLQaoBIRAMGgtBqwEhEAwZC0GsASEQDBgLQa0BIRAMFwtBrgEhEAwWC0EBIRAMFQtBrwEhEAwUC0GwASEQDBMLQbEBIRAMEgtBswEhEAwRC0GyASEQDBALQbQBIRAMDwtBtQEhEAwOC0G2ASEQDA0LQbcBIRAMDAtBuAEhEAwLC0G5ASEQDAoLQboBIRAMCQtBuwEhEAwIC0HGASEQDAcLQbwBIRAMBgtBvQEhEAwFC0G+ASEQDAQLQb8BIRAMAwtBwAEhEAwCC0HCASEQDAELQcEBIRALA0ACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQCAQDscBAAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxweHyAhIyUoP0BBREVGR0hJSktMTU9QUVJT3gNXWVtcXWBiZWZnaGlqa2xtb3BxcnN0dXZ3eHl6e3x9foABggGFAYYBhwGJAYsBjAGNAY4BjwGQAZEBlAGVAZYBlwGYAZkBmgGbAZwBnQGeAZ8BoAGhAaIBowGkAaUBpgGnAagBqQGqAasBrAGtAa4BrwGwAbEBsgGzAbQBtQG2AbcBuAG5AboBuwG8Ab0BvgG/AcABwQHCAcMBxAHFAcYBxwHIAckBygHLAcwBzQHOAc8B0AHRAdIB0wHUAdUB1gHXAdgB2QHaAdsB3AHdAd4B4AHhAeIB4wHkAeUB5gHnAegB6QHqAesB7AHtAe4B7wHwAfEB8gHzAZkCpAKwAv4C/gILIAEiBCACRw3zAUHdASEQDP8DCyABIhAgAkcN3QFBwwEhEAz+AwsgASIBIAJHDZABQfcAIRAM/QMLIAEiASACRw2GAUHvACEQDPwDCyABIgEgAkcNf0HqACEQDPsDCyABIgEgAkcNe0HoACEQDPoDCyABIgEgAkcNeEHmACEQDPkDCyABIgEgAkcNGkEYIRAM+AMLIAEiASACRw0UQRIhEAz3AwsgASIBIAJHDVlBxQAhEAz2AwsgASIBIAJHDUpBPyEQDPUDCyABIgEgAkcNSEE8IRAM9AMLIAEiASACRw1BQTEhEAzzAwsgAC0ALkEBRg3rAwyHAgsgACABIgEgAhDAgICAAEEBRw3mASAAQgA3AyAM5wELIAAgASIBIAIQtICAgAAiEA3nASABIQEM9QILAkAgASIBIAJHDQBBBiEQDPADCyAAIAFBAWoiASACELuAgIAAIhAN6AEgASEBDDELIABCADcDIEESIRAM1QMLIAEiECACRw0rQR0hEAztAwsCQCABIgEgAkYNACABQQFqIQFBECEQDNQDC0EHIRAM7AMLIABCACAAKQMgIhEgAiABIhBrrSISfSITIBMgEVYbNwMgIBEgElYiFEUN5QFBCCEQDOsDCwJAIAEiASACRg0AIABBiYCAgAA2AgggACABNgIEIAEhAUEUIRAM0gMLQQkhEAzqAwsgASEBIAApAyBQDeQBIAEhAQzyAgsCQCABIgEgAkcNAEELIRAM6QMLIAAgAUEBaiIBIAIQtoCAgAAiEA3lASABIQEM8gILIAAgASIBIAIQuICAgAAiEA3lASABIQEM8gILIAAgASIBIAIQuICAgAAiEA3mASABIQEMDQsgACABIgEgAhC6gICAACIQDecBIAEhAQzwAgsCQCABIgEgAkcNAEEPIRAM5QMLIAEtAAAiEEE7Rg0IIBBBDUcN6AEgAUEBaiEBDO8CCyAAIAEiASACELqAgIAAIhAN6AEgASEBDPICCwNAAkAgAS0AAEHwtYCAAGotAAAiEEEBRg0AIBBBAkcN6wEgACgCBCEQIABBADYCBCAAIBAgAUEBaiIBELmAgIAAIhAN6gEgASEBDPQCCyABQQFqIgEgAkcNAAtBEiEQDOIDCyAAIAEiASACELqAgIAAIhAN6QEgASEBDAoLIAEiASACRw0GQRshEAzgAwsCQCABIgEgAkcNAEEWIRAM4AMLIABBioCAgAA2AgggACABNgIEIAAgASACELiAgIAAIhAN6gEgASEBQSAhEAzGAwsCQCABIgEgAkYNAANAAkAgAS0AAEHwt4CAAGotAAAiEEECRg0AAkAgEEF/ag4E5QHsAQDrAewBCyABQQFqIQFBCCEQDMgDCyABQQFqIgEgAkcNAAtBFSEQDN8DC0EVIRAM3gMLA0ACQCABLQAAQfC5gIAAai0AACIQQQJGDQAgEEF/ag4E3gHsAeAB6wHsAQsgAUEBaiIBIAJHDQALQRghEAzdAwsCQCABIgEgAkYNACAAQYuAgIAANgIIIAAgATYCBCABIQFBByEQDMQDC0EZIRAM3AMLIAFBAWohAQwCCwJAIAEiFCACRw0AQRohEAzbAwsgFCEBAkAgFC0AAEFzag4U3QLuAu4C7gLuAu4C7gLuAu4C7gLuAu4C7gLuAu4C7gLuAu4C7gIA7gILQQAhECAAQQA2AhwgAEGvi4CAADYCECAAQQI2AgwgACAUQQFqNgIUDNoDCwJAIAEtAAAiEEE7Rg0AIBBBDUcN6AEgAUEBaiEBDOUCCyABQQFqIQELQSIhEAy/AwsCQCABIhAgAkcNAEEcIRAM2AMLQgAhESAQIQEgEC0AAEFQag435wHmAQECAwQFBgcIAAAAAAAAAAkKCwwNDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADxAREhMUAAtBHiEQDL0DC0ICIREM5QELQgMhEQzkAQtCBCERDOMBC0IFIREM4gELQgYhEQzhAQtCByERDOABC0IIIREM3wELQgkhEQzeAQtCCiERDN0BC0ILIREM3AELQgwhEQzbAQtCDSERDNoBC0IOIREM2QELQg8hEQzYAQtCCiERDNcBC0ILIREM1gELQgwhEQzVAQtCDSERDNQBC0IOIREM0wELQg8hEQzSAQtCACERAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQCAQLQAAQVBqDjflAeQBAAECAwQFBgfmAeYB5gHmAeYB5gHmAQgJCgsMDeYB5gHmAeYB5gHmAeYB5gHmAeYB5gHmAeYB5gHmAeYB5gHmAeYB5gHmAeYB5gHmAeYB5gEODxAREhPmAQtCAiERDOQBC0IDIREM4wELQgQhEQziAQtCBSERDOEBC0IGIREM4AELQgchEQzfAQtCCCERDN4BC0IJIREM3QELQgohEQzcAQtCCyERDNsBC0IMIREM2gELQg0hEQzZAQtCDiERDNgBC0IPIREM1wELQgohEQzWAQtCCyERDNUBC0IMIREM1AELQg0hEQzTAQtCDiERDNIBC0IPIREM0QELIABCACAAKQMgIhEgAiABIhBrrSISfSITIBMgEVYbNwMgIBEgElYiFEUN0gFBHyEQDMADCwJAIAEiASACRg0AIABBiYCAgAA2AgggACABNgIEIAEhAUEkIRAMpwMLQSAhEAy/AwsgACABIhAgAhC+gICAAEF/ag4FtgEAxQIB0QHSAQtBESEQDKQDCyAAQQE6AC8gECEBDLsDCyABIgEgAkcN0gFBJCEQDLsDCyABIg0gAkcNHkHGACEQDLoDCyAAIAEiASACELKAgIAAIhAN1AEgASEBDLUBCyABIhAgAkcNJkHQACEQDLgDCwJAIAEiASACRw0AQSghEAy4AwsgAEEANgIEIABBjICAgAA2AgggACABIAEQsYCAgAAiEA3TASABIQEM2AELAkAgASIQIAJHDQBBKSEQDLcDCyAQLQAAIgFBIEYNFCABQQlHDdMBIBBBAWohAQwVCwJAIAEiASACRg0AIAFBAWohAQwXC0EqIRAMtQMLAkAgASIQIAJHDQBBKyEQDLUDCwJAIBAtAAAiAUEJRg0AIAFBIEcN1QELIAAtACxBCEYN0wEgECEBDJEDCwJAIAEiASACRw0AQSwhEAy0AwsgAS0AAEEKRw3VASABQQFqIQEMyQILIAEiDiACRw3VAUEvIRAMsgMLA0ACQCABLQAAIhBBIEYNAAJAIBBBdmoOBADcAdwBANoBCyABIQEM4AELIAFBAWoiASACRw0AC0ExIRAMsQMLQTIhECABIhQgAkYNsAMgAiAUayAAKAIAIgFqIRUgFCABa0EDaiEWAkADQCAULQAAIhdBIHIgFyAXQb9/akH/AXFBGkkbQf8BcSABQfC7gIAAai0AAEcNAQJAIAFBA0cNAEEGIQEMlgMLIAFBAWohASAUQQFqIhQgAkcNAAsgACAVNgIADLEDCyAAQQA2AgAgFCEBDNkBC0EzIRAgASIUIAJGDa8DIAIgFGsgACgCACIBaiEVIBQgAWtBCGohFgJAA0AgFC0AACIXQSByIBcgF0G/f2pB/wFxQRpJG0H/AXEgAUH0u4CAAGotAABHDQECQCABQQhHDQBBBSEBDJUDCyABQQFqIQEgFEEBaiIUIAJHDQALIAAgFTYCAAywAwsgAEEANgIAIBQhAQzYAQtBNCEQIAEiFCACRg2uAyACIBRrIAAoAgAiAWohFSAUIAFrQQVqIRYCQANAIBQtAAAiF0EgciAXIBdBv39qQf8BcUEaSRtB/wFxIAFB0MKAgABqLQAARw0BAkAgAUEFRw0AQQchAQyUAwsgAUEBaiEBIBRBAWoiFCACRw0ACyAAIBU2AgAMrwMLIABBADYCACAUIQEM1wELAkAgASIBIAJGDQADQAJAIAEtAABBgL6AgABqLQAAIhBBAUYNACAQQQJGDQogASEBDN0BCyABQQFqIgEgAkcNAAtBMCEQDK4DC0EwIRAMrQMLAkAgASIBIAJGDQADQAJAIAEtAAAiEEEgRg0AIBBBdmoOBNkB2gHaAdkB2gELIAFBAWoiASACRw0AC0E4IRAMrQMLQTghEAysAwsDQAJAIAEtAAAiEEEgRg0AIBBBCUcNAwsgAUEBaiIBIAJHDQALQTwhEAyrAwsDQAJAIAEtAAAiEEEgRg0AAkACQCAQQXZqDgTaAQEB2gEACyAQQSxGDdsBCyABIQEMBAsgAUEBaiIBIAJHDQALQT8hEAyqAwsgASEBDNsBC0HAACEQIAEiFCACRg2oAyACIBRrIAAoAgAiAWohFiAUIAFrQQZqIRcCQANAIBQtAABBIHIgAUGAwICAAGotAABHDQEgAUEGRg2OAyABQQFqIQEgFEEBaiIUIAJHDQALIAAgFjYCAAypAwsgAEEANgIAIBQhAQtBNiEQDI4DCwJAIAEiDyACRw0AQcEAIRAMpwMLIABBjICAgAA2AgggACAPNgIEIA8hASAALQAsQX9qDgTNAdUB1wHZAYcDCyABQQFqIQEMzAELAkAgASIBIAJGDQADQAJAIAEtAAAiEEEgciAQIBBBv39qQf8BcUEaSRtB/wFxIhBBCUYNACAQQSBGDQACQAJAAkACQCAQQZ1/ag4TAAMDAwMDAwMBAwMDAwMDAwMDAgMLIAFBAWohAUExIRAMkQMLIAFBAWohAUEyIRAMkAMLIAFBAWohAUEzIRAMjwMLIAEhAQzQAQsgAUEBaiIBIAJHDQALQTUhEAylAwtBNSEQDKQDCwJAIAEiASACRg0AA0ACQCABLQAAQYC8gIAAai0AAEEBRg0AIAEhAQzTAQsgAUEBaiIBIAJHDQALQT0hEAykAwtBPSEQDKMDCyAAIAEiASACELCAgIAAIhAN1gEgASEBDAELIBBBAWohAQtBPCEQDIcDCwJAIAEiASACRw0AQcIAIRAMoAMLAkADQAJAIAEtAABBd2oOGAAC/gL+AoQD/gL+Av4C/gL+Av4C/gL+Av4C/gL+Av4C/gL+Av4C/gL+Av4CAP4CCyABQQFqIgEgAkcNAAtBwgAhEAygAwsgAUEBaiEBIAAtAC1BAXFFDb0BIAEhAQtBLCEQDIUDCyABIgEgAkcN0wFBxAAhEAydAwsDQAJAIAEtAABBkMCAgABqLQAAQQFGDQAgASEBDLcCCyABQQFqIgEgAkcNAAtBxQAhEAycAwsgDS0AACIQQSBGDbMBIBBBOkcNgQMgACgCBCEBIABBADYCBCAAIAEgDRCvgICAACIBDdABIA1BAWohAQyzAgtBxwAhECABIg0gAkYNmgMgAiANayAAKAIAIgFqIRYgDSABa0EFaiEXA0AgDS0AACIUQSByIBQgFEG/f2pB/wFxQRpJG0H/AXEgAUGQwoCAAGotAABHDYADIAFBBUYN9AIgAUEBaiEBIA1BAWoiDSACRw0ACyAAIBY2AgAMmgMLQcgAIRAgASINIAJGDZkDIAIgDWsgACgCACIBaiEWIA0gAWtBCWohFwNAIA0tAAAiFEEgciAUIBRBv39qQf8BcUEaSRtB/wFxIAFBlsKAgABqLQAARw3/AgJAIAFBCUcNAEECIQEM9QILIAFBAWohASANQQFqIg0gAkcNAAsgACAWNgIADJkDCwJAIAEiDSACRw0AQckAIRAMmQMLAkACQCANLQAAIgFBIHIgASABQb9/akH/AXFBGkkbQf8BcUGSf2oOBwCAA4ADgAOAA4ADAYADCyANQQFqIQFBPiEQDIADCyANQQFqIQFBPyEQDP8CC0HKACEQIAEiDSACRg2XAyACIA1rIAAoAgAiAWohFiANIAFrQQFqIRcDQCANLQAAIhRBIHIgFCAUQb9/akH/AXFBGkkbQf8BcSABQaDCgIAAai0AAEcN/QIgAUEBRg3wAiABQQFqIQEgDUEBaiINIAJHDQALIAAgFjYCAAyXAwtBywAhECABIg0gAkYNlgMgAiANayAAKAIAIgFqIRYgDSABa0EOaiEXA0AgDS0AACIUQSByIBQgFEG/f2pB/wFxQRpJG0H/AXEgAUGiwoCAAGotAABHDfwCIAFBDkYN8AIgAUEBaiEBIA1BAWoiDSACRw0ACyAAIBY2AgAMlgMLQcwAIRAgASINIAJGDZUDIAIgDWsgACgCACIBaiEWIA0gAWtBD2ohFwNAIA0tAAAiFEEgciAUIBRBv39qQf8BcUEaSRtB/wFxIAFBwMKAgABqLQAARw37AgJAIAFBD0cNAEEDIQEM8QILIAFBAWohASANQQFqIg0gAkcNAAsgACAWNgIADJUDC0HNACEQIAEiDSACRg2UAyACIA1rIAAoAgAiAWohFiANIAFrQQVqIRcDQCANLQAAIhRBIHIgFCAUQb9/akH/AXFBGkkbQf8BcSABQdDCgIAAai0AAEcN+gICQCABQQVHDQBBBCEBDPACCyABQQFqIQEgDUEBaiINIAJHDQALIAAgFjYCAAyUAwsCQCABIg0gAkcNAEHOACEQDJQDCwJAAkACQAJAIA0tAAAiAUEgciABIAFBv39qQf8BcUEaSRtB/wFxQZ1/ag4TAP0C/QL9Av0C/QL9Av0C/QL9Av0C/QL9AgH9Av0C/QICA/0CCyANQQFqIQFBwQAhEAz9AgsgDUEBaiEBQcIAIRAM/AILIA1BAWohAUHDACEQDPsCCyANQQFqIQFBxAAhEAz6AgsCQCABIgEgAkYNACAAQY2AgIAANgIIIAAgATYCBCABIQFBxQAhEAz6AgtBzwAhEAySAwsgECEBAkACQCAQLQAAQXZqDgQBqAKoAgCoAgsgEEEBaiEBC0EnIRAM+AILAkAgASIBIAJHDQBB0QAhEAyRAwsCQCABLQAAQSBGDQAgASEBDI0BCyABQQFqIQEgAC0ALUEBcUUNxwEgASEBDIwBCyABIhcgAkcNyAFB0gAhEAyPAwtB0wAhECABIhQgAkYNjgMgAiAUayAAKAIAIgFqIRYgFCABa0EBaiEXA0AgFC0AACABQdbCgIAAai0AAEcNzAEgAUEBRg3HASABQQFqIQEgFEEBaiIUIAJHDQALIAAgFjYCAAyOAwsCQCABIgEgAkcNAEHVACEQDI4DCyABLQAAQQpHDcwBIAFBAWohAQzHAQsCQCABIgEgAkcNAEHWACEQDI0DCwJAAkAgAS0AAEF2ag4EAM0BzQEBzQELIAFBAWohAQzHAQsgAUEBaiEBQcoAIRAM8wILIAAgASIBIAIQroCAgAAiEA3LASABIQFBzQAhEAzyAgsgAC0AKUEiRg2FAwymAgsCQCABIgEgAkcNAEHbACEQDIoDC0EAIRRBASEXQQEhFkEAIRACQAJAAkACQAJAAkACQAJAAkAgAS0AAEFQag4K1AHTAQABAgMEBQYI1QELQQIhEAwGC0EDIRAMBQtBBCEQDAQLQQUhEAwDC0EGIRAMAgtBByEQDAELQQghEAtBACEXQQAhFkEAIRQMzAELQQkhEEEBIRRBACEXQQAhFgzLAQsCQCABIgEgAkcNAEHdACEQDIkDCyABLQAAQS5HDcwBIAFBAWohAQymAgsgASIBIAJHDcwBQd8AIRAMhwMLAkAgASIBIAJGDQAgAEGOgICAADYCCCAAIAE2AgQgASEBQdAAIRAM7gILQeAAIRAMhgMLQeEAIRAgASIBIAJGDYUDIAIgAWsgACgCACIUaiEWIAEgFGtBA2ohFwNAIAEtAAAgFEHiwoCAAGotAABHDc0BIBRBA0YNzAEgFEEBaiEUIAFBAWoiASACRw0ACyAAIBY2AgAMhQMLQeIAIRAgASIBIAJGDYQDIAIgAWsgACgCACIUaiEWIAEgFGtBAmohFwNAIAEtAAAgFEHmwoCAAGotAABHDcwBIBRBAkYNzgEgFEEBaiEUIAFBAWoiASACRw0ACyAAIBY2AgAMhAMLQeMAIRAgASIBIAJGDYMDIAIgAWsgACgCACIUaiEWIAEgFGtBA2ohFwNAIAEtAAAgFEHpwoCAAGotAABHDcsBIBRBA0YNzgEgFEEBaiEUIAFBAWoiASACRw0ACyAAIBY2AgAMgwMLAkAgASIBIAJHDQBB5QAhEAyDAwsgACABQQFqIgEgAhCogICAACIQDc0BIAEhAUHWACEQDOkCCwJAIAEiASACRg0AA0ACQCABLQAAIhBBIEYNAAJAAkACQCAQQbh/ag4LAAHPAc8BzwHPAc8BzwHPAc8BAs8BCyABQQFqIQFB0gAhEAztAgsgAUEBaiEBQdMAIRAM7AILIAFBAWohAUHUACEQDOsCCyABQQFqIgEgAkcNAAtB5AAhEAyCAwtB5AAhEAyBAwsDQAJAIAEtAABB8MKAgABqLQAAIhBBAUYNACAQQX5qDgPPAdAB0QHSAQsgAUEBaiIBIAJHDQALQeYAIRAMgAMLAkAgASIBIAJGDQAgAUEBaiEBDAMLQecAIRAM/wILA0ACQCABLQAAQfDEgIAAai0AACIQQQFGDQACQCAQQX5qDgTSAdMB1AEA1QELIAEhAUHXACEQDOcCCyABQQFqIgEgAkcNAAtB6AAhEAz+AgsCQCABIgEgAkcNAEHpACEQDP4CCwJAIAEtAAAiEEF2ag4augHVAdUBvAHVAdUB1QHVAdUB1QHVAdUB1QHVAdUB1QHVAdUB1QHVAdUB1QHKAdUB1QEA0wELIAFBAWohAQtBBiEQDOMCCwNAAkAgAS0AAEHwxoCAAGotAABBAUYNACABIQEMngILIAFBAWoiASACRw0AC0HqACEQDPsCCwJAIAEiASACRg0AIAFBAWohAQwDC0HrACEQDPoCCwJAIAEiASACRw0AQewAIRAM+gILIAFBAWohAQwBCwJAIAEiASACRw0AQe0AIRAM+QILIAFBAWohAQtBBCEQDN4CCwJAIAEiFCACRw0AQe4AIRAM9wILIBQhAQJAAkACQCAULQAAQfDIgIAAai0AAEF/ag4H1AHVAdYBAJwCAQLXAQsgFEEBaiEBDAoLIBRBAWohAQzNAQtBACEQIABBADYCHCAAQZuSgIAANgIQIABBBzYCDCAAIBRBAWo2AhQM9gILAkADQAJAIAEtAABB8MiAgABqLQAAIhBBBEYNAAJAAkAgEEF/ag4H0gHTAdQB2QEABAHZAQsgASEBQdoAIRAM4AILIAFBAWohAUHcACEQDN8CCyABQQFqIgEgAkcNAAtB7wAhEAz2AgsgAUEBaiEBDMsBCwJAIAEiFCACRw0AQfAAIRAM9QILIBQtAABBL0cN1AEgFEEBaiEBDAYLAkAgASIUIAJHDQBB8QAhEAz0AgsCQCAULQAAIgFBL0cNACAUQQFqIQFB3QAhEAzbAgsgAUF2aiIEQRZLDdMBQQEgBHRBiYCAAnFFDdMBDMoCCwJAIAEiASACRg0AIAFBAWohAUHeACEQDNoCC0HyACEQDPICCwJAIAEiFCACRw0AQfQAIRAM8gILIBQhAQJAIBQtAABB8MyAgABqLQAAQX9qDgPJApQCANQBC0HhACEQDNgCCwJAIAEiFCACRg0AA0ACQCAULQAAQfDKgIAAai0AACIBQQNGDQACQCABQX9qDgLLAgDVAQsgFCEBQd8AIRAM2gILIBRBAWoiFCACRw0AC0HzACEQDPECC0HzACEQDPACCwJAIAEiASACRg0AIABBj4CAgAA2AgggACABNgIEIAEhAUHgACEQDNcCC0H1ACEQDO8CCwJAIAEiASACRw0AQfYAIRAM7wILIABBj4CAgAA2AgggACABNgIEIAEhAQtBAyEQDNQCCwNAIAEtAABBIEcNwwIgAUEBaiIBIAJHDQALQfcAIRAM7AILAkAgASIBIAJHDQBB+AAhEAzsAgsgAS0AAEEgRw3OASABQQFqIQEM7wELIAAgASIBIAIQrICAgAAiEA3OASABIQEMjgILAkAgASIEIAJHDQBB+gAhEAzqAgsgBC0AAEHMAEcN0QEgBEEBaiEBQRMhEAzPAQsCQCABIgQgAkcNAEH7ACEQDOkCCyACIARrIAAoAgAiAWohFCAEIAFrQQVqIRADQCAELQAAIAFB8M6AgABqLQAARw3QASABQQVGDc4BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQfsAIRAM6AILAkAgASIEIAJHDQBB/AAhEAzoAgsCQAJAIAQtAABBvX9qDgwA0QHRAdEB0QHRAdEB0QHRAdEB0QEB0QELIARBAWohAUHmACEQDM8CCyAEQQFqIQFB5wAhEAzOAgsCQCABIgQgAkcNAEH9ACEQDOcCCyACIARrIAAoAgAiAWohFCAEIAFrQQJqIRACQANAIAQtAAAgAUHtz4CAAGotAABHDc8BIAFBAkYNASABQQFqIQEgBEEBaiIEIAJHDQALIAAgFDYCAEH9ACEQDOcCCyAAQQA2AgAgEEEBaiEBQRAhEAzMAQsCQCABIgQgAkcNAEH+ACEQDOYCCyACIARrIAAoAgAiAWohFCAEIAFrQQVqIRACQANAIAQtAAAgAUH2zoCAAGotAABHDc4BIAFBBUYNASABQQFqIQEgBEEBaiIEIAJHDQALIAAgFDYCAEH+ACEQDOYCCyAAQQA2AgAgEEEBaiEBQRYhEAzLAQsCQCABIgQgAkcNAEH/ACEQDOUCCyACIARrIAAoAgAiAWohFCAEIAFrQQNqIRACQANAIAQtAAAgAUH8zoCAAGotAABHDc0BIAFBA0YNASABQQFqIQEgBEEBaiIEIAJHDQALIAAgFDYCAEH/ACEQDOUCCyAAQQA2AgAgEEEBaiEBQQUhEAzKAQsCQCABIgQgAkcNAEGAASEQDOQCCyAELQAAQdkARw3LASAEQQFqIQFBCCEQDMkBCwJAIAEiBCACRw0AQYEBIRAM4wILAkACQCAELQAAQbJ/ag4DAMwBAcwBCyAEQQFqIQFB6wAhEAzKAgsgBEEBaiEBQewAIRAMyQILAkAgASIEIAJHDQBBggEhEAziAgsCQAJAIAQtAABBuH9qDggAywHLAcsBywHLAcsBAcsBCyAEQQFqIQFB6gAhEAzJAgsgBEEBaiEBQe0AIRAMyAILAkAgASIEIAJHDQBBgwEhEAzhAgsgAiAEayAAKAIAIgFqIRAgBCABa0ECaiEUAkADQCAELQAAIAFBgM+AgABqLQAARw3JASABQQJGDQEgAUEBaiEBIARBAWoiBCACRw0ACyAAIBA2AgBBgwEhEAzhAgtBACEQIABBADYCACAUQQFqIQEMxgELAkAgASIEIAJHDQBBhAEhEAzgAgsgAiAEayAAKAIAIgFqIRQgBCABa0EEaiEQAkADQCAELQAAIAFBg8+AgABqLQAARw3IASABQQRGDQEgAUEBaiEBIARBAWoiBCACRw0ACyAAIBQ2AgBBhAEhEAzgAgsgAEEANgIAIBBBAWohAUEjIRAMxQELAkAgASIEIAJHDQBBhQEhEAzfAgsCQAJAIAQtAABBtH9qDggAyAHIAcgByAHIAcgBAcgBCyAEQQFqIQFB7wAhEAzGAgsgBEEBaiEBQfAAIRAMxQILAkAgASIEIAJHDQBBhgEhEAzeAgsgBC0AAEHFAEcNxQEgBEEBaiEBDIMCCwJAIAEiBCACRw0AQYcBIRAM3QILIAIgBGsgACgCACIBaiEUIAQgAWtBA2ohEAJAA0AgBC0AACABQYjPgIAAai0AAEcNxQEgAUEDRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQYcBIRAM3QILIABBADYCACAQQQFqIQFBLSEQDMIBCwJAIAEiBCACRw0AQYgBIRAM3AILIAIgBGsgACgCACIBaiEUIAQgAWtBCGohEAJAA0AgBC0AACABQdDPgIAAai0AAEcNxAEgAUEIRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQYgBIRAM3AILIABBADYCACAQQQFqIQFBKSEQDMEBCwJAIAEiASACRw0AQYkBIRAM2wILQQEhECABLQAAQd8ARw3AASABQQFqIQEMgQILAkAgASIEIAJHDQBBigEhEAzaAgsgAiAEayAAKAIAIgFqIRQgBCABa0EBaiEQA0AgBC0AACABQYzPgIAAai0AAEcNwQEgAUEBRg2vAiABQQFqIQEgBEEBaiIEIAJHDQALIAAgFDYCAEGKASEQDNkCCwJAIAEiBCACRw0AQYsBIRAM2QILIAIgBGsgACgCACIBaiEUIAQgAWtBAmohEAJAA0AgBC0AACABQY7PgIAAai0AAEcNwQEgAUECRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQYsBIRAM2QILIABBADYCACAQQQFqIQFBAiEQDL4BCwJAIAEiBCACRw0AQYwBIRAM2AILIAIgBGsgACgCACIBaiEUIAQgAWtBAWohEAJAA0AgBC0AACABQfDPgIAAai0AAEcNwAEgAUEBRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQYwBIRAM2AILIABBADYCACAQQQFqIQFBHyEQDL0BCwJAIAEiBCACRw0AQY0BIRAM1wILIAIgBGsgACgCACIBaiEUIAQgAWtBAWohEAJAA0AgBC0AACABQfLPgIAAai0AAEcNvwEgAUEBRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQY0BIRAM1wILIABBADYCACAQQQFqIQFBCSEQDLwBCwJAIAEiBCACRw0AQY4BIRAM1gILAkACQCAELQAAQbd/ag4HAL8BvwG/Ab8BvwEBvwELIARBAWohAUH4ACEQDL0CCyAEQQFqIQFB+QAhEAy8AgsCQCABIgQgAkcNAEGPASEQDNUCCyACIARrIAAoAgAiAWohFCAEIAFrQQVqIRACQANAIAQtAAAgAUGRz4CAAGotAABHDb0BIAFBBUYNASABQQFqIQEgBEEBaiIEIAJHDQALIAAgFDYCAEGPASEQDNUCCyAAQQA2AgAgEEEBaiEBQRghEAy6AQsCQCABIgQgAkcNAEGQASEQDNQCCyACIARrIAAoAgAiAWohFCAEIAFrQQJqIRACQANAIAQtAAAgAUGXz4CAAGotAABHDbwBIAFBAkYNASABQQFqIQEgBEEBaiIEIAJHDQALIAAgFDYCAEGQASEQDNQCCyAAQQA2AgAgEEEBaiEBQRchEAy5AQsCQCABIgQgAkcNAEGRASEQDNMCCyACIARrIAAoAgAiAWohFCAEIAFrQQZqIRACQANAIAQtAAAgAUGaz4CAAGotAABHDbsBIAFBBkYNASABQQFqIQEgBEEBaiIEIAJHDQALIAAgFDYCAEGRASEQDNMCCyAAQQA2AgAgEEEBaiEBQRUhEAy4AQsCQCABIgQgAkcNAEGSASEQDNICCyACIARrIAAoAgAiAWohFCAEIAFrQQVqIRACQANAIAQtAAAgAUGhz4CAAGotAABHDboBIAFBBUYNASABQQFqIQEgBEEBaiIEIAJHDQALIAAgFDYCAEGSASEQDNICCyAAQQA2AgAgEEEBaiEBQR4hEAy3AQsCQCABIgQgAkcNAEGTASEQDNECCyAELQAAQcwARw24ASAEQQFqIQFBCiEQDLYBCwJAIAQgAkcNAEGUASEQDNACCwJAAkAgBC0AAEG/f2oODwC5AbkBuQG5AbkBuQG5AbkBuQG5AbkBuQG5AQG5AQsgBEEBaiEBQf4AIRAMtwILIARBAWohAUH/ACEQDLYCCwJAIAQgAkcNAEGVASEQDM8CCwJAAkAgBC0AAEG/f2oOAwC4AQG4AQsgBEEBaiEBQf0AIRAMtgILIARBAWohBEGAASEQDLUCCwJAIAQgAkcNAEGWASEQDM4CCyACIARrIAAoAgAiAWohFCAEIAFrQQFqIRACQANAIAQtAAAgAUGnz4CAAGotAABHDbYBIAFBAUYNASABQQFqIQEgBEEBaiIEIAJHDQALIAAgFDYCAEGWASEQDM4CCyAAQQA2AgAgEEEBaiEBQQshEAyzAQsCQCAEIAJHDQBBlwEhEAzNAgsCQAJAAkACQCAELQAAQVNqDiMAuAG4AbgBuAG4AbgBuAG4AbgBuAG4AbgBuAG4AbgBuAG4AbgBuAG4AbgBuAG4AQG4AbgBuAG4AbgBArgBuAG4AQO4AQsgBEEBaiEBQfsAIRAMtgILIARBAWohAUH8ACEQDLUCCyAEQQFqIQRBgQEhEAy0AgsgBEEBaiEEQYIBIRAMswILAkAgBCACRw0AQZgBIRAMzAILIAIgBGsgACgCACIBaiEUIAQgAWtBBGohEAJAA0AgBC0AACABQanPgIAAai0AAEcNtAEgAUEERg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQZgBIRAMzAILIABBADYCACAQQQFqIQFBGSEQDLEBCwJAIAQgAkcNAEGZASEQDMsCCyACIARrIAAoAgAiAWohFCAEIAFrQQVqIRACQANAIAQtAAAgAUGuz4CAAGotAABHDbMBIAFBBUYNASABQQFqIQEgBEEBaiIEIAJHDQALIAAgFDYCAEGZASEQDMsCCyAAQQA2AgAgEEEBaiEBQQYhEAywAQsCQCAEIAJHDQBBmgEhEAzKAgsgAiAEayAAKAIAIgFqIRQgBCABa0EBaiEQAkADQCAELQAAIAFBtM+AgABqLQAARw2yASABQQFGDQEgAUEBaiEBIARBAWoiBCACRw0ACyAAIBQ2AgBBmgEhEAzKAgsgAEEANgIAIBBBAWohAUEcIRAMrwELAkAgBCACRw0AQZsBIRAMyQILIAIgBGsgACgCACIBaiEUIAQgAWtBAWohEAJAA0AgBC0AACABQbbPgIAAai0AAEcNsQEgAUEBRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQZsBIRAMyQILIABBADYCACAQQQFqIQFBJyEQDK4BCwJAIAQgAkcNAEGcASEQDMgCCwJAAkAgBC0AAEGsf2oOAgABsQELIARBAWohBEGGASEQDK8CCyAEQQFqIQRBhwEhEAyuAgsCQCAEIAJHDQBBnQEhEAzHAgsgAiAEayAAKAIAIgFqIRQgBCABa0EBaiEQAkADQCAELQAAIAFBuM+AgABqLQAARw2vASABQQFGDQEgAUEBaiEBIARBAWoiBCACRw0ACyAAIBQ2AgBBnQEhEAzHAgsgAEEANgIAIBBBAWohAUEmIRAMrAELAkAgBCACRw0AQZ4BIRAMxgILIAIgBGsgACgCACIBaiEUIAQgAWtBAWohEAJAA0AgBC0AACABQbrPgIAAai0AAEcNrgEgAUEBRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQZ4BIRAMxgILIABBADYCACAQQQFqIQFBAyEQDKsBCwJAIAQgAkcNAEGfASEQDMUCCyACIARrIAAoAgAiAWohFCAEIAFrQQJqIRACQANAIAQtAAAgAUHtz4CAAGotAABHDa0BIAFBAkYNASABQQFqIQEgBEEBaiIEIAJHDQALIAAgFDYCAEGfASEQDMUCCyAAQQA2AgAgEEEBaiEBQQwhEAyqAQsCQCAEIAJHDQBBoAEhEAzEAgsgAiAEayAAKAIAIgFqIRQgBCABa0EDaiEQAkADQCAELQAAIAFBvM+AgABqLQAARw2sASABQQNGDQEgAUEBaiEBIARBAWoiBCACRw0ACyAAIBQ2AgBBoAEhEAzEAgsgAEEANgIAIBBBAWohAUENIRAMqQELAkAgBCACRw0AQaEBIRAMwwILAkACQCAELQAAQbp/ag4LAKwBrAGsAawBrAGsAawBrAGsAQGsAQsgBEEBaiEEQYsBIRAMqgILIARBAWohBEGMASEQDKkCCwJAIAQgAkcNAEGiASEQDMICCyAELQAAQdAARw2pASAEQQFqIQQM6QELAkAgBCACRw0AQaMBIRAMwQILAkACQCAELQAAQbd/ag4HAaoBqgGqAaoBqgEAqgELIARBAWohBEGOASEQDKgCCyAEQQFqIQFBIiEQDKYBCwJAIAQgAkcNAEGkASEQDMACCyACIARrIAAoAgAiAWohFCAEIAFrQQFqIRACQANAIAQtAAAgAUHAz4CAAGotAABHDagBIAFBAUYNASABQQFqIQEgBEEBaiIEIAJHDQALIAAgFDYCAEGkASEQDMACCyAAQQA2AgAgEEEBaiEBQR0hEAylAQsCQCAEIAJHDQBBpQEhEAy/AgsCQAJAIAQtAABBrn9qDgMAqAEBqAELIARBAWohBEGQASEQDKYCCyAEQQFqIQFBBCEQDKQBCwJAIAQgAkcNAEGmASEQDL4CCwJAAkACQAJAAkAgBC0AAEG/f2oOFQCqAaoBqgGqAaoBqgGqAaoBqgGqAQGqAaoBAqoBqgEDqgGqAQSqAQsgBEEBaiEEQYgBIRAMqAILIARBAWohBEGJASEQDKcCCyAEQQFqIQRBigEhEAymAgsgBEEBaiEEQY8BIRAMpQILIARBAWohBEGRASEQDKQCCwJAIAQgAkcNAEGnASEQDL0CCyACIARrIAAoAgAiAWohFCAEIAFrQQJqIRACQANAIAQtAAAgAUHtz4CAAGotAABHDaUBIAFBAkYNASABQQFqIQEgBEEBaiIEIAJHDQALIAAgFDYCAEGnASEQDL0CCyAAQQA2AgAgEEEBaiEBQREhEAyiAQsCQCAEIAJHDQBBqAEhEAy8AgsgAiAEayAAKAIAIgFqIRQgBCABa0ECaiEQAkADQCAELQAAIAFBws+AgABqLQAARw2kASABQQJGDQEgAUEBaiEBIARBAWoiBCACRw0ACyAAIBQ2AgBBqAEhEAy8AgsgAEEANgIAIBBBAWohAUEsIRAMoQELAkAgBCACRw0AQakBIRAMuwILIAIgBGsgACgCACIBaiEUIAQgAWtBBGohEAJAA0AgBC0AACABQcXPgIAAai0AAEcNowEgAUEERg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQakBIRAMuwILIABBADYCACAQQQFqIQFBKyEQDKABCwJAIAQgAkcNAEGqASEQDLoCCyACIARrIAAoAgAiAWohFCAEIAFrQQJqIRACQANAIAQtAAAgAUHKz4CAAGotAABHDaIBIAFBAkYNASABQQFqIQEgBEEBaiIEIAJHDQALIAAgFDYCAEGqASEQDLoCCyAAQQA2AgAgEEEBaiEBQRQhEAyfAQsCQCAEIAJHDQBBqwEhEAy5AgsCQAJAAkACQCAELQAAQb5/ag4PAAECpAGkAaQBpAGkAaQBpAGkAaQBpAGkAQOkAQsgBEEBaiEEQZMBIRAMogILIARBAWohBEGUASEQDKECCyAEQQFqIQRBlQEhEAygAgsgBEEBaiEEQZYBIRAMnwILAkAgBCACRw0AQawBIRAMuAILIAQtAABBxQBHDZ8BIARBAWohBAzgAQsCQCAEIAJHDQBBrQEhEAy3AgsgAiAEayAAKAIAIgFqIRQgBCABa0ECaiEQAkADQCAELQAAIAFBzc+AgABqLQAARw2fASABQQJGDQEgAUEBaiEBIARBAWoiBCACRw0ACyAAIBQ2AgBBrQEhEAy3AgsgAEEANgIAIBBBAWohAUEOIRAMnAELAkAgBCACRw0AQa4BIRAMtgILIAQtAABB0ABHDZ0BIARBAWohAUElIRAMmwELAkAgBCACRw0AQa8BIRAMtQILIAIgBGsgACgCACIBaiEUIAQgAWtBCGohEAJAA0AgBC0AACABQdDPgIAAai0AAEcNnQEgAUEIRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQa8BIRAMtQILIABBADYCACAQQQFqIQFBKiEQDJoBCwJAIAQgAkcNAEGwASEQDLQCCwJAAkAgBC0AAEGrf2oOCwCdAZ0BnQGdAZ0BnQGdAZ0BnQEBnQELIARBAWohBEGaASEQDJsCCyAEQQFqIQRBmwEhEAyaAgsCQCAEIAJHDQBBsQEhEAyzAgsCQAJAIAQtAABBv39qDhQAnAGcAZwBnAGcAZwBnAGcAZwBnAGcAZwBnAGcAZwBnAGcAZwBAZwBCyAEQQFqIQRBmQEhEAyaAgsgBEEBaiEEQZwBIRAMmQILAkAgBCACRw0AQbIBIRAMsgILIAIgBGsgACgCACIBaiEUIAQgAWtBA2ohEAJAA0AgBC0AACABQdnPgIAAai0AAEcNmgEgAUEDRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQbIBIRAMsgILIABBADYCACAQQQFqIQFBISEQDJcBCwJAIAQgAkcNAEGzASEQDLECCyACIARrIAAoAgAiAWohFCAEIAFrQQZqIRACQANAIAQtAAAgAUHdz4CAAGotAABHDZkBIAFBBkYNASABQQFqIQEgBEEBaiIEIAJHDQALIAAgFDYCAEGzASEQDLECCyAAQQA2AgAgEEEBaiEBQRohEAyWAQsCQCAEIAJHDQBBtAEhEAywAgsCQAJAAkAgBC0AAEG7f2oOEQCaAZoBmgGaAZoBmgGaAZoBmgEBmgGaAZoBmgGaAQKaAQsgBEEBaiEEQZ0BIRAMmAILIARBAWohBEGeASEQDJcCCyAEQQFqIQRBnwEhEAyWAgsCQCAEIAJHDQBBtQEhEAyvAgsgAiAEayAAKAIAIgFqIRQgBCABa0EFaiEQAkADQCAELQAAIAFB5M+AgABqLQAARw2XASABQQVGDQEgAUEBaiEBIARBAWoiBCACRw0ACyAAIBQ2AgBBtQEhEAyvAgsgAEEANgIAIBBBAWohAUEoIRAMlAELAkAgBCACRw0AQbYBIRAMrgILIAIgBGsgACgCACIBaiEUIAQgAWtBAmohEAJAA0AgBC0AACABQerPgIAAai0AAEcNlgEgAUECRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQbYBIRAMrgILIABBADYCACAQQQFqIQFBByEQDJMBCwJAIAQgAkcNAEG3ASEQDK0CCwJAAkAgBC0AAEG7f2oODgCWAZYBlgGWAZYBlgGWAZYBlgGWAZYBlgEBlgELIARBAWohBEGhASEQDJQCCyAEQQFqIQRBogEhEAyTAgsCQCAEIAJHDQBBuAEhEAysAgsgAiAEayAAKAIAIgFqIRQgBCABa0ECaiEQAkADQCAELQAAIAFB7c+AgABqLQAARw2UASABQQJGDQEgAUEBaiEBIARBAWoiBCACRw0ACyAAIBQ2AgBBuAEhEAysAgsgAEEANgIAIBBBAWohAUESIRAMkQELAkAgBCACRw0AQbkBIRAMqwILIAIgBGsgACgCACIBaiEUIAQgAWtBAWohEAJAA0AgBC0AACABQfDPgIAAai0AAEcNkwEgAUEBRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQbkBIRAMqwILIABBADYCACAQQQFqIQFBICEQDJABCwJAIAQgAkcNAEG6ASEQDKoCCyACIARrIAAoAgAiAWohFCAEIAFrQQFqIRACQANAIAQtAAAgAUHyz4CAAGotAABHDZIBIAFBAUYNASABQQFqIQEgBEEBaiIEIAJHDQALIAAgFDYCAEG6ASEQDKoCCyAAQQA2AgAgEEEBaiEBQQ8hEAyPAQsCQCAEIAJHDQBBuwEhEAypAgsCQAJAIAQtAABBt39qDgcAkgGSAZIBkgGSAQGSAQsgBEEBaiEEQaUBIRAMkAILIARBAWohBEGmASEQDI8CCwJAIAQgAkcNAEG8ASEQDKgCCyACIARrIAAoAgAiAWohFCAEIAFrQQdqIRACQANAIAQtAAAgAUH0z4CAAGotAABHDZABIAFBB0YNASABQQFqIQEgBEEBaiIEIAJHDQALIAAgFDYCAEG8ASEQDKgCCyAAQQA2AgAgEEEBaiEBQRshEAyNAQsCQCAEIAJHDQBBvQEhEAynAgsCQAJAAkAgBC0AAEG+f2oOEgCRAZEBkQGRAZEBkQGRAZEBkQEBkQGRAZEBkQGRAZEBApEBCyAEQQFqIQRBpAEhEAyPAgsgBEEBaiEEQacBIRAMjgILIARBAWohBEGoASEQDI0CCwJAIAQgAkcNAEG+ASEQDKYCCyAELQAAQc4ARw2NASAEQQFqIQQMzwELAkAgBCACRw0AQb8BIRAMpQILAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAgBC0AAEG/f2oOFQABAgOcAQQFBpwBnAGcAQcICQoLnAEMDQ4PnAELIARBAWohAUHoACEQDJoCCyAEQQFqIQFB6QAhEAyZAgsgBEEBaiEBQe4AIRAMmAILIARBAWohAUHyACEQDJcCCyAEQQFqIQFB8wAhEAyWAgsgBEEBaiEBQfYAIRAMlQILIARBAWohAUH3ACEQDJQCCyAEQQFqIQFB+gAhEAyTAgsgBEEBaiEEQYMBIRAMkgILIARBAWohBEGEASEQDJECCyAEQQFqIQRBhQEhEAyQAgsgBEEBaiEEQZIBIRAMjwILIARBAWohBEGYASEQDI4CCyAEQQFqIQRBoAEhEAyNAgsgBEEBaiEEQaMBIRAMjAILIARBAWohBEGqASEQDIsCCwJAIAQgAkYNACAAQZCAgIAANgIIIAAgBDYCBEGrASEQDIsCC0HAASEQDKMCCyAAIAUgAhCqgICAACIBDYsBIAUhAQxcCwJAIAYgAkYNACAGQQFqIQUMjQELQcIBIRAMoQILA0ACQCAQLQAAQXZqDgSMAQAAjwEACyAQQQFqIhAgAkcNAAtBwwEhEAygAgsCQCAHIAJGDQAgAEGRgICAADYCCCAAIAc2AgQgByEBQQEhEAyHAgtBxAEhEAyfAgsCQCAHIAJHDQBBxQEhEAyfAgsCQAJAIActAABBdmoOBAHOAc4BAM4BCyAHQQFqIQYMjQELIAdBAWohBQyJAQsCQCAHIAJHDQBBxgEhEAyeAgsCQAJAIActAABBdmoOFwGPAY8BAY8BjwGPAY8BjwGPAY8BjwGPAY8BjwGPAY8BjwGPAY8BjwGPAQCPAQsgB0EBaiEHC0GwASEQDIQCCwJAIAggAkcNAEHIASEQDJ0CCyAILQAAQSBHDY0BIABBADsBMiAIQQFqIQFBswEhEAyDAgsgASEXAkADQCAXIgcgAkYNASAHLQAAQVBqQf8BcSIQQQpPDcwBAkAgAC8BMiIUQZkzSw0AIAAgFEEKbCIUOwEyIBBB//8DcyAUQf7/A3FJDQAgB0EBaiEXIAAgFCAQaiIQOwEyIBBB//8DcUHoB0kNAQsLQQAhECAAQQA2AhwgAEHBiYCAADYCECAAQQ02AgwgACAHQQFqNgIUDJwCC0HHASEQDJsCCyAAIAggAhCugICAACIQRQ3KASAQQRVHDYwBIABByAE2AhwgACAINgIUIABByZeAgAA2AhAgAEEVNgIMQQAhEAyaAgsCQCAJIAJHDQBBzAEhEAyaAgtBACEUQQEhF0EBIRZBACEQAkACQAJAAkACQAJAAkACQAJAIAktAABBUGoOCpYBlQEAAQIDBAUGCJcBC0ECIRAMBgtBAyEQDAULQQQhEAwEC0EFIRAMAwtBBiEQDAILQQchEAwBC0EIIRALQQAhF0EAIRZBACEUDI4BC0EJIRBBASEUQQAhF0EAIRYMjQELAkAgCiACRw0AQc4BIRAMmQILIAotAABBLkcNjgEgCkEBaiEJDMoBCyALIAJHDY4BQdABIRAMlwILAkAgCyACRg0AIABBjoCAgAA2AgggACALNgIEQbcBIRAM/gELQdEBIRAMlgILAkAgBCACRw0AQdIBIRAMlgILIAIgBGsgACgCACIQaiEUIAQgEGtBBGohCwNAIAQtAAAgEEH8z4CAAGotAABHDY4BIBBBBEYN6QEgEEEBaiEQIARBAWoiBCACRw0ACyAAIBQ2AgBB0gEhEAyVAgsgACAMIAIQrICAgAAiAQ2NASAMIQEMuAELAkAgBCACRw0AQdQBIRAMlAILIAIgBGsgACgCACIQaiEUIAQgEGtBAWohDANAIAQtAAAgEEGB0ICAAGotAABHDY8BIBBBAUYNjgEgEEEBaiEQIARBAWoiBCACRw0ACyAAIBQ2AgBB1AEhEAyTAgsCQCAEIAJHDQBB1gEhEAyTAgsgAiAEayAAKAIAIhBqIRQgBCAQa0ECaiELA0AgBC0AACAQQYPQgIAAai0AAEcNjgEgEEECRg2QASAQQQFqIRAgBEEBaiIEIAJHDQALIAAgFDYCAEHWASEQDJICCwJAIAQgAkcNAEHXASEQDJICCwJAAkAgBC0AAEG7f2oOEACPAY8BjwGPAY8BjwGPAY8BjwGPAY8BjwGPAY8BAY8BCyAEQQFqIQRBuwEhEAz5AQsgBEEBaiEEQbwBIRAM+AELAkAgBCACRw0AQdgBIRAMkQILIAQtAABByABHDYwBIARBAWohBAzEAQsCQCAEIAJGDQAgAEGQgICAADYCCCAAIAQ2AgRBvgEhEAz3AQtB2QEhEAyPAgsCQCAEIAJHDQBB2gEhEAyPAgsgBC0AAEHIAEYNwwEgAEEBOgAoDLkBCyAAQQI6AC8gACAEIAIQpoCAgAAiEA2NAUHCASEQDPQBCyAALQAoQX9qDgK3AbkBuAELA0ACQCAELQAAQXZqDgQAjgGOAQCOAQsgBEEBaiIEIAJHDQALQd0BIRAMiwILIABBADoALyAALQAtQQRxRQ2EAgsgAEEAOgAvIABBAToANCABIQEMjAELIBBBFUYN2gEgAEEANgIcIAAgATYCFCAAQaeOgIAANgIQIABBEjYCDEEAIRAMiAILAkAgACAQIAIQtICAgAAiBA0AIBAhAQyBAgsCQCAEQRVHDQAgAEEDNgIcIAAgEDYCFCAAQbCYgIAANgIQIABBFTYCDEEAIRAMiAILIABBADYCHCAAIBA2AhQgAEGnjoCAADYCECAAQRI2AgxBACEQDIcCCyAQQRVGDdYBIABBADYCHCAAIAE2AhQgAEHajYCAADYCECAAQRQ2AgxBACEQDIYCCyAAKAIEIRcgAEEANgIEIBAgEadqIhYhASAAIBcgECAWIBQbIhAQtYCAgAAiFEUNjQEgAEEHNgIcIAAgEDYCFCAAIBQ2AgxBACEQDIUCCyAAIAAvATBBgAFyOwEwIAEhAQtBKiEQDOoBCyAQQRVGDdEBIABBADYCHCAAIAE2AhQgAEGDjICAADYCECAAQRM2AgxBACEQDIICCyAQQRVGDc8BIABBADYCHCAAIAE2AhQgAEGaj4CAADYCECAAQSI2AgxBACEQDIECCyAAKAIEIRAgAEEANgIEAkAgACAQIAEQt4CAgAAiEA0AIAFBAWohAQyNAQsgAEEMNgIcIAAgEDYCDCAAIAFBAWo2AhRBACEQDIACCyAQQRVGDcwBIABBADYCHCAAIAE2AhQgAEGaj4CAADYCECAAQSI2AgxBACEQDP8BCyAAKAIEIRAgAEEANgIEAkAgACAQIAEQt4CAgAAiEA0AIAFBAWohAQyMAQsgAEENNgIcIAAgEDYCDCAAIAFBAWo2AhRBACEQDP4BCyAQQRVGDckBIABBADYCHCAAIAE2AhQgAEHGjICAADYCECAAQSM2AgxBACEQDP0BCyAAKAIEIRAgAEEANgIEAkAgACAQIAEQuYCAgAAiEA0AIAFBAWohAQyLAQsgAEEONgIcIAAgEDYCDCAAIAFBAWo2AhRBACEQDPwBCyAAQQA2AhwgACABNgIUIABBwJWAgAA2AhAgAEECNgIMQQAhEAz7AQsgEEEVRg3FASAAQQA2AhwgACABNgIUIABBxoyAgAA2AhAgAEEjNgIMQQAhEAz6AQsgAEEQNgIcIAAgATYCFCAAIBA2AgxBACEQDPkBCyAAKAIEIQQgAEEANgIEAkAgACAEIAEQuYCAgAAiBA0AIAFBAWohAQzxAQsgAEERNgIcIAAgBDYCDCAAIAFBAWo2AhRBACEQDPgBCyAQQRVGDcEBIABBADYCHCAAIAE2AhQgAEHGjICAADYCECAAQSM2AgxBACEQDPcBCyAAKAIEIRAgAEEANgIEAkAgACAQIAEQuYCAgAAiEA0AIAFBAWohAQyIAQsgAEETNgIcIAAgEDYCDCAAIAFBAWo2AhRBACEQDPYBCyAAKAIEIQQgAEEANgIEAkAgACAEIAEQuYCAgAAiBA0AIAFBAWohAQztAQsgAEEUNgIcIAAgBDYCDCAAIAFBAWo2AhRBACEQDPUBCyAQQRVGDb0BIABBADYCHCAAIAE2AhQgAEGaj4CAADYCECAAQSI2AgxBACEQDPQBCyAAKAIEIRAgAEEANgIEAkAgACAQIAEQt4CAgAAiEA0AIAFBAWohAQyGAQsgAEEWNgIcIAAgEDYCDCAAIAFBAWo2AhRBACEQDPMBCyAAKAIEIQQgAEEANgIEAkAgACAEIAEQt4CAgAAiBA0AIAFBAWohAQzpAQsgAEEXNgIcIAAgBDYCDCAAIAFBAWo2AhRBACEQDPIBCyAAQQA2AhwgACABNgIUIABBzZOAgAA2AhAgAEEMNgIMQQAhEAzxAQtCASERCyAQQQFqIQECQCAAKQMgIhJC//////////8PVg0AIAAgEkIEhiARhDcDICABIQEMhAELIABBADYCHCAAIAE2AhQgAEGtiYCAADYCECAAQQw2AgxBACEQDO8BCyAAQQA2AhwgACAQNgIUIABBzZOAgAA2AhAgAEEMNgIMQQAhEAzuAQsgACgCBCEXIABBADYCBCAQIBGnaiIWIQEgACAXIBAgFiAUGyIQELWAgIAAIhRFDXMgAEEFNgIcIAAgEDYCFCAAIBQ2AgxBACEQDO0BCyAAQQA2AhwgACAQNgIUIABBqpyAgAA2AhAgAEEPNgIMQQAhEAzsAQsgACAQIAIQtICAgAAiAQ0BIBAhAQtBDiEQDNEBCwJAIAFBFUcNACAAQQI2AhwgACAQNgIUIABBsJiAgAA2AhAgAEEVNgIMQQAhEAzqAQsgAEEANgIcIAAgEDYCFCAAQaeOgIAANgIQIABBEjYCDEEAIRAM6QELIAFBAWohEAJAIAAvATAiAUGAAXFFDQACQCAAIBAgAhC7gICAACIBDQAgECEBDHALIAFBFUcNugEgAEEFNgIcIAAgEDYCFCAAQfmXgIAANgIQIABBFTYCDEEAIRAM6QELAkAgAUGgBHFBoARHDQAgAC0ALUECcQ0AIABBADYCHCAAIBA2AhQgAEGWk4CAADYCECAAQQQ2AgxBACEQDOkBCyAAIBAgAhC9gICAABogECEBAkACQAJAAkACQCAAIBAgAhCzgICAAA4WAgEABAQEBAQEBAQEBAQEBAQEBAQEAwQLIABBAToALgsgACAALwEwQcAAcjsBMCAQIQELQSYhEAzRAQsgAEEjNgIcIAAgEDYCFCAAQaWWgIAANgIQIABBFTYCDEEAIRAM6QELIABBADYCHCAAIBA2AhQgAEHVi4CAADYCECAAQRE2AgxBACEQDOgBCyAALQAtQQFxRQ0BQcMBIRAMzgELAkAgDSACRg0AA0ACQCANLQAAQSBGDQAgDSEBDMQBCyANQQFqIg0gAkcNAAtBJSEQDOcBC0ElIRAM5gELIAAoAgQhBCAAQQA2AgQgACAEIA0Qr4CAgAAiBEUNrQEgAEEmNgIcIAAgBDYCDCAAIA1BAWo2AhRBACEQDOUBCyAQQRVGDasBIABBADYCHCAAIAE2AhQgAEH9jYCAADYCECAAQR02AgxBACEQDOQBCyAAQSc2AhwgACABNgIUIAAgEDYCDEEAIRAM4wELIBAhAUEBIRQCQAJAAkACQAJAAkACQCAALQAsQX5qDgcGBQUDAQIABQsgACAALwEwQQhyOwEwDAMLQQIhFAwBC0EEIRQLIABBAToALCAAIAAvATAgFHI7ATALIBAhAQtBKyEQDMoBCyAAQQA2AhwgACAQNgIUIABBq5KAgAA2AhAgAEELNgIMQQAhEAziAQsgAEEANgIcIAAgATYCFCAAQeGPgIAANgIQIABBCjYCDEEAIRAM4QELIABBADoALCAQIQEMvQELIBAhAUEBIRQCQAJAAkACQAJAIAAtACxBe2oOBAMBAgAFCyAAIAAvATBBCHI7ATAMAwtBAiEUDAELQQQhFAsgAEEBOgAsIAAgAC8BMCAUcjsBMAsgECEBC0EpIRAMxQELIABBADYCHCAAIAE2AhQgAEHwlICAADYCECAAQQM2AgxBACEQDN0BCwJAIA4tAABBDUcNACAAKAIEIQEgAEEANgIEAkAgACABIA4QsYCAgAAiAQ0AIA5BAWohAQx1CyAAQSw2AhwgACABNgIMIAAgDkEBajYCFEEAIRAM3QELIAAtAC1BAXFFDQFBxAEhEAzDAQsCQCAOIAJHDQBBLSEQDNwBCwJAAkADQAJAIA4tAABBdmoOBAIAAAMACyAOQQFqIg4gAkcNAAtBLSEQDN0BCyAAKAIEIQEgAEEANgIEAkAgACABIA4QsYCAgAAiAQ0AIA4hAQx0CyAAQSw2AhwgACAONgIUIAAgATYCDEEAIRAM3AELIAAoAgQhASAAQQA2AgQCQCAAIAEgDhCxgICAACIBDQAgDkEBaiEBDHMLIABBLDYCHCAAIAE2AgwgACAOQQFqNgIUQQAhEAzbAQsgACgCBCEEIABBADYCBCAAIAQgDhCxgICAACIEDaABIA4hAQzOAQsgEEEsRw0BIAFBAWohEEEBIQECQAJAAkACQAJAIAAtACxBe2oOBAMBAgQACyAQIQEMBAtBAiEBDAELQQQhAQsgAEEBOgAsIAAgAC8BMCABcjsBMCAQIQEMAQsgACAALwEwQQhyOwEwIBAhAQtBOSEQDL8BCyAAQQA6ACwgASEBC0E0IRAMvQELIAAgAC8BMEEgcjsBMCABIQEMAgsgACgCBCEEIABBADYCBAJAIAAgBCABELGAgIAAIgQNACABIQEMxwELIABBNzYCHCAAIAE2AhQgACAENgIMQQAhEAzUAQsgAEEIOgAsIAEhAQtBMCEQDLkBCwJAIAAtAChBAUYNACABIQEMBAsgAC0ALUEIcUUNkwEgASEBDAMLIAAtADBBIHENlAFBxQEhEAy3AQsCQCAPIAJGDQACQANAAkAgDy0AAEFQaiIBQf8BcUEKSQ0AIA8hAUE1IRAMugELIAApAyAiEUKZs+bMmbPmzBlWDQEgACARQgp+IhE3AyAgESABrUL/AYMiEkJ/hVYNASAAIBEgEnw3AyAgD0EBaiIPIAJHDQALQTkhEAzRAQsgACgCBCECIABBADYCBCAAIAIgD0EBaiIEELGAgIAAIgINlQEgBCEBDMMBC0E5IRAMzwELAkAgAC8BMCIBQQhxRQ0AIAAtAChBAUcNACAALQAtQQhxRQ2QAQsgACABQff7A3FBgARyOwEwIA8hAQtBNyEQDLQBCyAAIAAvATBBEHI7ATAMqwELIBBBFUYNiwEgAEEANgIcIAAgATYCFCAAQfCOgIAANgIQIABBHDYCDEEAIRAMywELIABBwwA2AhwgACABNgIMIAAgDUEBajYCFEEAIRAMygELAkAgAS0AAEE6Rw0AIAAoAgQhECAAQQA2AgQCQCAAIBAgARCvgICAACIQDQAgAUEBaiEBDGMLIABBwwA2AhwgACAQNgIMIAAgAUEBajYCFEEAIRAMygELIABBADYCHCAAIAE2AhQgAEGxkYCAADYCECAAQQo2AgxBACEQDMkBCyAAQQA2AhwgACABNgIUIABBoJmAgAA2AhAgAEEeNgIMQQAhEAzIAQsgAEEANgIACyAAQYASOwEqIAAgF0EBaiIBIAIQqICAgAAiEA0BIAEhAQtBxwAhEAysAQsgEEEVRw2DASAAQdEANgIcIAAgATYCFCAAQeOXgIAANgIQIABBFTYCDEEAIRAMxAELIAAoAgQhECAAQQA2AgQCQCAAIBAgARCngICAACIQDQAgASEBDF4LIABB0gA2AhwgACABNgIUIAAgEDYCDEEAIRAMwwELIABBADYCHCAAIBQ2AhQgAEHBqICAADYCECAAQQc2AgwgAEEANgIAQQAhEAzCAQsgACgCBCEQIABBADYCBAJAIAAgECABEKeAgIAAIhANACABIQEMXQsgAEHTADYCHCAAIAE2AhQgACAQNgIMQQAhEAzBAQtBACEQIABBADYCHCAAIAE2AhQgAEGAkYCAADYCECAAQQk2AgwMwAELIBBBFUYNfSAAQQA2AhwgACABNgIUIABBlI2AgAA2AhAgAEEhNgIMQQAhEAy/AQtBASEWQQAhF0EAIRRBASEQCyAAIBA6ACsgAUEBaiEBAkACQCAALQAtQRBxDQACQAJAAkAgAC0AKg4DAQACBAsgFkUNAwwCCyAUDQEMAgsgF0UNAQsgACgCBCEQIABBADYCBAJAIAAgECABEK2AgIAAIhANACABIQEMXAsgAEHYADYCHCAAIAE2AhQgACAQNgIMQQAhEAy+AQsgACgCBCEEIABBADYCBAJAIAAgBCABEK2AgIAAIgQNACABIQEMrQELIABB2QA2AhwgACABNgIUIAAgBDYCDEEAIRAMvQELIAAoAgQhBCAAQQA2AgQCQCAAIAQgARCtgICAACIEDQAgASEBDKsBCyAAQdoANgIcIAAgATYCFCAAIAQ2AgxBACEQDLwBCyAAKAIEIQQgAEEANgIEAkAgACAEIAEQrYCAgAAiBA0AIAEhAQypAQsgAEHcADYCHCAAIAE2AhQgACAENgIMQQAhEAy7AQsCQCABLQAAQVBqIhBB/wFxQQpPDQAgACAQOgAqIAFBAWohAUHPACEQDKIBCyAAKAIEIQQgAEEANgIEAkAgACAEIAEQrYCAgAAiBA0AIAEhAQynAQsgAEHeADYCHCAAIAE2AhQgACAENgIMQQAhEAy6AQsgAEEANgIAIBdBAWohAQJAIAAtAClBI08NACABIQEMWQsgAEEANgIcIAAgATYCFCAAQdOJgIAANgIQIABBCDYCDEEAIRAMuQELIABBADYCAAtBACEQIABBADYCHCAAIAE2AhQgAEGQs4CAADYCECAAQQg2AgwMtwELIABBADYCACAXQQFqIQECQCAALQApQSFHDQAgASEBDFYLIABBADYCHCAAIAE2AhQgAEGbioCAADYCECAAQQg2AgxBACEQDLYBCyAAQQA2AgAgF0EBaiEBAkAgAC0AKSIQQV1qQQtPDQAgASEBDFULAkAgEEEGSw0AQQEgEHRBygBxRQ0AIAEhAQxVC0EAIRAgAEEANgIcIAAgATYCFCAAQfeJgIAANgIQIABBCDYCDAy1AQsgEEEVRg1xIABBADYCHCAAIAE2AhQgAEG5jYCAADYCECAAQRo2AgxBACEQDLQBCyAAKAIEIRAgAEEANgIEAkAgACAQIAEQp4CAgAAiEA0AIAEhAQxUCyAAQeUANgIcIAAgATYCFCAAIBA2AgxBACEQDLMBCyAAKAIEIRAgAEEANgIEAkAgACAQIAEQp4CAgAAiEA0AIAEhAQxNCyAAQdIANgIcIAAgATYCFCAAIBA2AgxBACEQDLIBCyAAKAIEIRAgAEEANgIEAkAgACAQIAEQp4CAgAAiEA0AIAEhAQxNCyAAQdMANgIcIAAgATYCFCAAIBA2AgxBACEQDLEBCyAAKAIEIRAgAEEANgIEAkAgACAQIAEQp4CAgAAiEA0AIAEhAQxRCyAAQeUANgIcIAAgATYCFCAAIBA2AgxBACEQDLABCyAAQQA2AhwgACABNgIUIABBxoqAgAA2AhAgAEEHNgIMQQAhEAyvAQsgACgCBCEQIABBADYCBAJAIAAgECABEKeAgIAAIhANACABIQEMSQsgAEHSADYCHCAAIAE2AhQgACAQNgIMQQAhEAyuAQsgACgCBCEQIABBADYCBAJAIAAgECABEKeAgIAAIhANACABIQEMSQsgAEHTADYCHCAAIAE2AhQgACAQNgIMQQAhEAytAQsgACgCBCEQIABBADYCBAJAIAAgECABEKeAgIAAIhANACABIQEMTQsgAEHlADYCHCAAIAE2AhQgACAQNgIMQQAhEAysAQsgAEEANgIcIAAgATYCFCAAQdyIgIAANgIQIABBBzYCDEEAIRAMqwELIBBBP0cNASABQQFqIQELQQUhEAyQAQtBACEQIABBADYCHCAAIAE2AhQgAEH9koCAADYCECAAQQc2AgwMqAELIAAoAgQhECAAQQA2AgQCQCAAIBAgARCngICAACIQDQAgASEBDEILIABB0gA2AhwgACABNgIUIAAgEDYCDEEAIRAMpwELIAAoAgQhECAAQQA2AgQCQCAAIBAgARCngICAACIQDQAgASEBDEILIABB0wA2AhwgACABNgIUIAAgEDYCDEEAIRAMpgELIAAoAgQhECAAQQA2AgQCQCAAIBAgARCngICAACIQDQAgASEBDEYLIABB5QA2AhwgACABNgIUIAAgEDYCDEEAIRAMpQELIAAoAgQhASAAQQA2AgQCQCAAIAEgFBCngICAACIBDQAgFCEBDD8LIABB0gA2AhwgACAUNgIUIAAgATYCDEEAIRAMpAELIAAoAgQhASAAQQA2AgQCQCAAIAEgFBCngICAACIBDQAgFCEBDD8LIABB0wA2AhwgACAUNgIUIAAgATYCDEEAIRAMowELIAAoAgQhASAAQQA2AgQCQCAAIAEgFBCngICAACIBDQAgFCEBDEMLIABB5QA2AhwgACAUNgIUIAAgATYCDEEAIRAMogELIABBADYCHCAAIBQ2AhQgAEHDj4CAADYCECAAQQc2AgxBACEQDKEBCyAAQQA2AhwgACABNgIUIABBw4+AgAA2AhAgAEEHNgIMQQAhEAygAQtBACEQIABBADYCHCAAIBQ2AhQgAEGMnICAADYCECAAQQc2AgwMnwELIABBADYCHCAAIBQ2AhQgAEGMnICAADYCECAAQQc2AgxBACEQDJ4BCyAAQQA2AhwgACAUNgIUIABB/pGAgAA2AhAgAEEHNgIMQQAhEAydAQsgAEEANgIcIAAgATYCFCAAQY6bgIAANgIQIABBBjYCDEEAIRAMnAELIBBBFUYNVyAAQQA2AhwgACABNgIUIABBzI6AgAA2AhAgAEEgNgIMQQAhEAybAQsgAEEANgIAIBBBAWohAUEkIRALIAAgEDoAKSAAKAIEIRAgAEEANgIEIAAgECABEKuAgIAAIhANVCABIQEMPgsgAEEANgIAC0EAIRAgAEEANgIcIAAgBDYCFCAAQfGbgIAANgIQIABBBjYCDAyXAQsgAUEVRg1QIABBADYCHCAAIAU2AhQgAEHwjICAADYCECAAQRs2AgxBACEQDJYBCyAAKAIEIQUgAEEANgIEIAAgBSAQEKmAgIAAIgUNASAQQQFqIQULQa0BIRAMewsgAEHBATYCHCAAIAU2AgwgACAQQQFqNgIUQQAhEAyTAQsgACgCBCEGIABBADYCBCAAIAYgEBCpgICAACIGDQEgEEEBaiEGC0GuASEQDHgLIABBwgE2AhwgACAGNgIMIAAgEEEBajYCFEEAIRAMkAELIABBADYCHCAAIAc2AhQgAEGXi4CAADYCECAAQQ02AgxBACEQDI8BCyAAQQA2AhwgACAINgIUIABB45CAgAA2AhAgAEEJNgIMQQAhEAyOAQsgAEEANgIcIAAgCDYCFCAAQZSNgIAANgIQIABBITYCDEEAIRAMjQELQQEhFkEAIRdBACEUQQEhEAsgACAQOgArIAlBAWohCAJAAkAgAC0ALUEQcQ0AAkACQAJAIAAtACoOAwEAAgQLIBZFDQMMAgsgFA0BDAILIBdFDQELIAAoAgQhECAAQQA2AgQgACAQIAgQrYCAgAAiEEUNPSAAQckBNgIcIAAgCDYCFCAAIBA2AgxBACEQDIwBCyAAKAIEIQQgAEEANgIEIAAgBCAIEK2AgIAAIgRFDXYgAEHKATYCHCAAIAg2AhQgACAENgIMQQAhEAyLAQsgACgCBCEEIABBADYCBCAAIAQgCRCtgICAACIERQ10IABBywE2AhwgACAJNgIUIAAgBDYCDEEAIRAMigELIAAoAgQhBCAAQQA2AgQgACAEIAoQrYCAgAAiBEUNciAAQc0BNgIcIAAgCjYCFCAAIAQ2AgxBACEQDIkBCwJAIAstAABBUGoiEEH/AXFBCk8NACAAIBA6ACogC0EBaiEKQbYBIRAMcAsgACgCBCEEIABBADYCBCAAIAQgCxCtgICAACIERQ1wIABBzwE2AhwgACALNgIUIAAgBDYCDEEAIRAMiAELIABBADYCHCAAIAQ2AhQgAEGQs4CAADYCECAAQQg2AgwgAEEANgIAQQAhEAyHAQsgAUEVRg0/IABBADYCHCAAIAw2AhQgAEHMjoCAADYCECAAQSA2AgxBACEQDIYBCyAAQYEEOwEoIAAoAgQhECAAQgA3AwAgACAQIAxBAWoiDBCrgICAACIQRQ04IABB0wE2AhwgACAMNgIUIAAgEDYCDEEAIRAMhQELIABBADYCAAtBACEQIABBADYCHCAAIAQ2AhQgAEHYm4CAADYCECAAQQg2AgwMgwELIAAoAgQhECAAQgA3AwAgACAQIAtBAWoiCxCrgICAACIQDQFBxgEhEAxpCyAAQQI6ACgMVQsgAEHVATYCHCAAIAs2AhQgACAQNgIMQQAhEAyAAQsgEEEVRg03IABBADYCHCAAIAQ2AhQgAEGkjICAADYCECAAQRA2AgxBACEQDH8LIAAtADRBAUcNNCAAIAQgAhC8gICAACIQRQ00IBBBFUcNNSAAQdwBNgIcIAAgBDYCFCAAQdWWgIAANgIQIABBFTYCDEEAIRAMfgtBACEQIABBADYCHCAAQa+LgIAANgIQIABBAjYCDCAAIBRBAWo2AhQMfQtBACEQDGMLQQIhEAxiC0ENIRAMYQtBDyEQDGALQSUhEAxfC0ETIRAMXgtBFSEQDF0LQRYhEAxcC0EXIRAMWwtBGCEQDFoLQRkhEAxZC0EaIRAMWAtBGyEQDFcLQRwhEAxWC0EdIRAMVQtBHyEQDFQLQSEhEAxTC0EjIRAMUgtBxgAhEAxRC0EuIRAMUAtBLyEQDE8LQTshEAxOC0E9IRAMTQtByAAhEAxMC0HJACEQDEsLQcsAIRAMSgtBzAAhEAxJC0HOACEQDEgLQdEAIRAMRwtB1QAhEAxGC0HYACEQDEULQdkAIRAMRAtB2wAhEAxDC0HkACEQDEILQeUAIRAMQQtB8QAhEAxAC0H0ACEQDD8LQY0BIRAMPgtBlwEhEAw9C0GpASEQDDwLQawBIRAMOwtBwAEhEAw6C0G5ASEQDDkLQa8BIRAMOAtBsQEhEAw3C0GyASEQDDYLQbQBIRAMNQtBtQEhEAw0C0G6ASEQDDMLQb0BIRAMMgtBvwEhEAwxC0HBASEQDDALIABBADYCHCAAIAQ2AhQgAEHpi4CAADYCECAAQR82AgxBACEQDEgLIABB2wE2AhwgACAENgIUIABB+paAgAA2AhAgAEEVNgIMQQAhEAxHCyAAQfgANgIcIAAgDDYCFCAAQcqYgIAANgIQIABBFTYCDEEAIRAMRgsgAEHRADYCHCAAIAU2AhQgAEGwl4CAADYCECAAQRU2AgxBACEQDEULIABB+QA2AhwgACABNgIUIAAgEDYCDEEAIRAMRAsgAEH4ADYCHCAAIAE2AhQgAEHKmICAADYCECAAQRU2AgxBACEQDEMLIABB5AA2AhwgACABNgIUIABB45eAgAA2AhAgAEEVNgIMQQAhEAxCCyAAQdcANgIcIAAgATYCFCAAQcmXgIAANgIQIABBFTYCDEEAIRAMQQsgAEEANgIcIAAgATYCFCAAQbmNgIAANgIQIABBGjYCDEEAIRAMQAsgAEHCADYCHCAAIAE2AhQgAEHjmICAADYCECAAQRU2AgxBACEQDD8LIABBADYCBCAAIA8gDxCxgICAACIERQ0BIABBOjYCHCAAIAQ2AgwgACAPQQFqNgIUQQAhEAw+CyAAKAIEIQQgAEEANgIEAkAgACAEIAEQsYCAgAAiBEUNACAAQTs2AhwgACAENgIMIAAgAUEBajYCFEEAIRAMPgsgAUEBaiEBDC0LIA9BAWohAQwtCyAAQQA2AhwgACAPNgIUIABB5JKAgAA2AhAgAEEENgIMQQAhEAw7CyAAQTY2AhwgACAENgIUIAAgAjYCDEEAIRAMOgsgAEEuNgIcIAAgDjYCFCAAIAQ2AgxBACEQDDkLIABB0AA2AhwgACABNgIUIABBkZiAgAA2AhAgAEEVNgIMQQAhEAw4CyANQQFqIQEMLAsgAEEVNgIcIAAgATYCFCAAQYKZgIAANgIQIABBFTYCDEEAIRAMNgsgAEEbNgIcIAAgATYCFCAAQZGXgIAANgIQIABBFTYCDEEAIRAMNQsgAEEPNgIcIAAgATYCFCAAQZGXgIAANgIQIABBFTYCDEEAIRAMNAsgAEELNgIcIAAgATYCFCAAQZGXgIAANgIQIABBFTYCDEEAIRAMMwsgAEEaNgIcIAAgATYCFCAAQYKZgIAANgIQIABBFTYCDEEAIRAMMgsgAEELNgIcIAAgATYCFCAAQYKZgIAANgIQIABBFTYCDEEAIRAMMQsgAEEKNgIcIAAgATYCFCAAQeSWgIAANgIQIABBFTYCDEEAIRAMMAsgAEEeNgIcIAAgATYCFCAAQfmXgIAANgIQIABBFTYCDEEAIRAMLwsgAEEANgIcIAAgEDYCFCAAQdqNgIAANgIQIABBFDYCDEEAIRAMLgsgAEEENgIcIAAgATYCFCAAQbCYgIAANgIQIABBFTYCDEEAIRAMLQsgAEEANgIAIAtBAWohCwtBuAEhEAwSCyAAQQA2AgAgEEEBaiEBQfUAIRAMEQsgASEBAkAgAC0AKUEFRw0AQeMAIRAMEQtB4gAhEAwQC0EAIRAgAEEANgIcIABB5JGAgAA2AhAgAEEHNgIMIAAgFEEBajYCFAwoCyAAQQA2AgAgF0EBaiEBQcAAIRAMDgtBASEBCyAAIAE6ACwgAEEANgIAIBdBAWohAQtBKCEQDAsLIAEhAQtBOCEQDAkLAkAgASIPIAJGDQADQAJAIA8tAABBgL6AgABqLQAAIgFBAUYNACABQQJHDQMgD0EBaiEBDAQLIA9BAWoiDyACRw0AC0E+IRAMIgtBPiEQDCELIABBADoALCAPIQEMAQtBCyEQDAYLQTohEAwFCyABQQFqIQFBLSEQDAQLIAAgAToALCAAQQA2AgAgFkEBaiEBQQwhEAwDCyAAQQA2AgAgF0EBaiEBQQohEAwCCyAAQQA2AgALIABBADoALCANIQFBCSEQDAALC0EAIRAgAEEANgIcIAAgCzYCFCAAQc2QgIAANgIQIABBCTYCDAwXC0EAIRAgAEEANgIcIAAgCjYCFCAAQemKgIAANgIQIABBCTYCDAwWC0EAIRAgAEEANgIcIAAgCTYCFCAAQbeQgIAANgIQIABBCTYCDAwVC0EAIRAgAEEANgIcIAAgCDYCFCAAQZyRgIAANgIQIABBCTYCDAwUC0EAIRAgAEEANgIcIAAgATYCFCAAQc2QgIAANgIQIABBCTYCDAwTC0EAIRAgAEEANgIcIAAgATYCFCAAQemKgIAANgIQIABBCTYCDAwSC0EAIRAgAEEANgIcIAAgATYCFCAAQbeQgIAANgIQIABBCTYCDAwRC0EAIRAgAEEANgIcIAAgATYCFCAAQZyRgIAANgIQIABBCTYCDAwQC0EAIRAgAEEANgIcIAAgATYCFCAAQZeVgIAANgIQIABBDzYCDAwPC0EAIRAgAEEANgIcIAAgATYCFCAAQZeVgIAANgIQIABBDzYCDAwOC0EAIRAgAEEANgIcIAAgATYCFCAAQcCSgIAANgIQIABBCzYCDAwNC0EAIRAgAEEANgIcIAAgATYCFCAAQZWJgIAANgIQIABBCzYCDAwMC0EAIRAgAEEANgIcIAAgATYCFCAAQeGPgIAANgIQIABBCjYCDAwLC0EAIRAgAEEANgIcIAAgATYCFCAAQfuPgIAANgIQIABBCjYCDAwKC0EAIRAgAEEANgIcIAAgATYCFCAAQfGZgIAANgIQIABBAjYCDAwJC0EAIRAgAEEANgIcIAAgATYCFCAAQcSUgIAANgIQIABBAjYCDAwIC0EAIRAgAEEANgIcIAAgATYCFCAAQfKVgIAANgIQIABBAjYCDAwHCyAAQQI2AhwgACABNgIUIABBnJqAgAA2AhAgAEEWNgIMQQAhEAwGC0EBIRAMBQtB1AAhECABIgQgAkYNBCADQQhqIAAgBCACQdjCgIAAQQoQxYCAgAAgAygCDCEEIAMoAggOAwEEAgALEMqAgIAAAAsgAEEANgIcIABBtZqAgAA2AhAgAEEXNgIMIAAgBEEBajYCFEEAIRAMAgsgAEEANgIcIAAgBDYCFCAAQcqagIAANgIQIABBCTYCDEEAIRAMAQsCQCABIgQgAkcNAEEiIRAMAQsgAEGJgICAADYCCCAAIAQ2AgRBISEQCyADQRBqJICAgIAAIBALrwEBAn8gASgCACEGAkACQCACIANGDQAgBCAGaiEEIAYgA2ogAmshByACIAZBf3MgBWoiBmohBQNAAkAgAi0AACAELQAARg0AQQIhBAwDCwJAIAYNAEEAIQQgBSECDAMLIAZBf2ohBiAEQQFqIQQgAkEBaiICIANHDQALIAchBiADIQILIABBATYCACABIAY2AgAgACACNgIEDwsgAUEANgIAIAAgBDYCACAAIAI2AgQLCgAgABDHgICAAAvyNgELfyOAgICAAEEQayIBJICAgIAAAkBBACgCoNCAgAANAEEAEMuAgIAAQYDUhIAAayICQdkASQ0AQQAhAwJAQQAoAuDTgIAAIgQNAEEAQn83AuzTgIAAQQBCgICEgICAwAA3AuTTgIAAQQAgAUEIakFwcUHYqtWqBXMiBDYC4NOAgABBAEEANgL004CAAEEAQQA2AsTTgIAAC0EAIAI2AszTgIAAQQBBgNSEgAA2AsjTgIAAQQBBgNSEgAA2ApjQgIAAQQAgBDYCrNCAgABBAEF/NgKo0ICAAANAIANBxNCAgABqIANBuNCAgABqIgQ2AgAgBCADQbDQgIAAaiIFNgIAIANBvNCAgABqIAU2AgAgA0HM0ICAAGogA0HA0ICAAGoiBTYCACAFIAQ2AgAgA0HU0ICAAGogA0HI0ICAAGoiBDYCACAEIAU2AgAgA0HQ0ICAAGogBDYCACADQSBqIgNBgAJHDQALQYDUhIAAQXhBgNSEgABrQQ9xQQBBgNSEgABBCGpBD3EbIgNqIgRBBGogAkFIaiIFIANrIgNBAXI2AgBBAEEAKALw04CAADYCpNCAgABBACADNgKU0ICAAEEAIAQ2AqDQgIAAQYDUhIAAIAVqQTg2AgQLAkACQAJAAkACQAJAAkACQAJAAkACQAJAIABB7AFLDQACQEEAKAKI0ICAACIGQRAgAEETakFwcSAAQQtJGyICQQN2IgR2IgNBA3FFDQACQAJAIANBAXEgBHJBAXMiBUEDdCIEQbDQgIAAaiIDIARBuNCAgABqKAIAIgQoAggiAkcNAEEAIAZBfiAFd3E2AojQgIAADAELIAMgAjYCCCACIAM2AgwLIARBCGohAyAEIAVBA3QiBUEDcjYCBCAEIAVqIgQgBCgCBEEBcjYCBAwMCyACQQAoApDQgIAAIgdNDQECQCADRQ0AAkACQCADIAR0QQIgBHQiA0EAIANrcnEiA0EAIANrcUF/aiIDIANBDHZBEHEiA3YiBEEFdkEIcSIFIANyIAQgBXYiA0ECdkEEcSIEciADIAR2IgNBAXZBAnEiBHIgAyAEdiIDQQF2QQFxIgRyIAMgBHZqIgRBA3QiA0Gw0ICAAGoiBSADQbjQgIAAaigCACIDKAIIIgBHDQBBACAGQX4gBHdxIgY2AojQgIAADAELIAUgADYCCCAAIAU2AgwLIAMgAkEDcjYCBCADIARBA3QiBGogBCACayIFNgIAIAMgAmoiACAFQQFyNgIEAkAgB0UNACAHQXhxQbDQgIAAaiECQQAoApzQgIAAIQQCQAJAIAZBASAHQQN2dCIIcQ0AQQAgBiAIcjYCiNCAgAAgAiEIDAELIAIoAgghCAsgCCAENgIMIAIgBDYCCCAEIAI2AgwgBCAINgIICyADQQhqIQNBACAANgKc0ICAAEEAIAU2ApDQgIAADAwLQQAoAozQgIAAIglFDQEgCUEAIAlrcUF/aiIDIANBDHZBEHEiA3YiBEEFdkEIcSIFIANyIAQgBXYiA0ECdkEEcSIEciADIAR2IgNBAXZBAnEiBHIgAyAEdiIDQQF2QQFxIgRyIAMgBHZqQQJ0QbjSgIAAaigCACIAKAIEQXhxIAJrIQQgACEFAkADQAJAIAUoAhAiAw0AIAVBFGooAgAiA0UNAgsgAygCBEF4cSACayIFIAQgBSAESSIFGyEEIAMgACAFGyEAIAMhBQwACwsgACgCGCEKAkAgACgCDCIIIABGDQAgACgCCCIDQQAoApjQgIAASRogCCADNgIIIAMgCDYCDAwLCwJAIABBFGoiBSgCACIDDQAgACgCECIDRQ0DIABBEGohBQsDQCAFIQsgAyIIQRRqIgUoAgAiAw0AIAhBEGohBSAIKAIQIgMNAAsgC0EANgIADAoLQX8hAiAAQb9/Sw0AIABBE2oiA0FwcSECQQAoAozQgIAAIgdFDQBBACELAkAgAkGAAkkNAEEfIQsgAkH///8HSw0AIANBCHYiAyADQYD+P2pBEHZBCHEiA3QiBCAEQYDgH2pBEHZBBHEiBHQiBSAFQYCAD2pBEHZBAnEiBXRBD3YgAyAEciAFcmsiA0EBdCACIANBFWp2QQFxckEcaiELC0EAIAJrIQQCQAJAAkACQCALQQJ0QbjSgIAAaigCACIFDQBBACEDQQAhCAwBC0EAIQMgAkEAQRkgC0EBdmsgC0EfRht0IQBBACEIA0ACQCAFKAIEQXhxIAJrIgYgBE8NACAGIQQgBSEIIAYNAEEAIQQgBSEIIAUhAwwDCyADIAVBFGooAgAiBiAGIAUgAEEddkEEcWpBEGooAgAiBUYbIAMgBhshAyAAQQF0IQAgBQ0ACwsCQCADIAhyDQBBACEIQQIgC3QiA0EAIANrciAHcSIDRQ0DIANBACADa3FBf2oiAyADQQx2QRBxIgN2IgVBBXZBCHEiACADciAFIAB2IgNBAnZBBHEiBXIgAyAFdiIDQQF2QQJxIgVyIAMgBXYiA0EBdkEBcSIFciADIAV2akECdEG40oCAAGooAgAhAwsgA0UNAQsDQCADKAIEQXhxIAJrIgYgBEkhAAJAIAMoAhAiBQ0AIANBFGooAgAhBQsgBiAEIAAbIQQgAyAIIAAbIQggBSEDIAUNAAsLIAhFDQAgBEEAKAKQ0ICAACACa08NACAIKAIYIQsCQCAIKAIMIgAgCEYNACAIKAIIIgNBACgCmNCAgABJGiAAIAM2AgggAyAANgIMDAkLAkAgCEEUaiIFKAIAIgMNACAIKAIQIgNFDQMgCEEQaiEFCwNAIAUhBiADIgBBFGoiBSgCACIDDQAgAEEQaiEFIAAoAhAiAw0ACyAGQQA2AgAMCAsCQEEAKAKQ0ICAACIDIAJJDQBBACgCnNCAgAAhBAJAAkAgAyACayIFQRBJDQAgBCACaiIAIAVBAXI2AgRBACAFNgKQ0ICAAEEAIAA2ApzQgIAAIAQgA2ogBTYCACAEIAJBA3I2AgQMAQsgBCADQQNyNgIEIAQgA2oiAyADKAIEQQFyNgIEQQBBADYCnNCAgABBAEEANgKQ0ICAAAsgBEEIaiEDDAoLAkBBACgClNCAgAAiACACTQ0AQQAoAqDQgIAAIgMgAmoiBCAAIAJrIgVBAXI2AgRBACAFNgKU0ICAAEEAIAQ2AqDQgIAAIAMgAkEDcjYCBCADQQhqIQMMCgsCQAJAQQAoAuDTgIAARQ0AQQAoAujTgIAAIQQMAQtBAEJ/NwLs04CAAEEAQoCAhICAgMAANwLk04CAAEEAIAFBDGpBcHFB2KrVqgVzNgLg04CAAEEAQQA2AvTTgIAAQQBBADYCxNOAgABBgIAEIQQLQQAhAwJAIAQgAkHHAGoiB2oiBkEAIARrIgtxIgggAksNAEEAQTA2AvjTgIAADAoLAkBBACgCwNOAgAAiA0UNAAJAQQAoArjTgIAAIgQgCGoiBSAETQ0AIAUgA00NAQtBACEDQQBBMDYC+NOAgAAMCgtBAC0AxNOAgABBBHENBAJAAkACQEEAKAKg0ICAACIERQ0AQcjTgIAAIQMDQAJAIAMoAgAiBSAESw0AIAUgAygCBGogBEsNAwsgAygCCCIDDQALC0EAEMuAgIAAIgBBf0YNBSAIIQYCQEEAKALk04CAACIDQX9qIgQgAHFFDQAgCCAAayAEIABqQQAgA2txaiEGCyAGIAJNDQUgBkH+////B0sNBQJAQQAoAsDTgIAAIgNFDQBBACgCuNOAgAAiBCAGaiIFIARNDQYgBSADSw0GCyAGEMuAgIAAIgMgAEcNAQwHCyAGIABrIAtxIgZB/v///wdLDQQgBhDLgICAACIAIAMoAgAgAygCBGpGDQMgACEDCwJAIANBf0YNACACQcgAaiAGTQ0AAkAgByAGa0EAKALo04CAACIEakEAIARrcSIEQf7///8HTQ0AIAMhAAwHCwJAIAQQy4CAgABBf0YNACAEIAZqIQYgAyEADAcLQQAgBmsQy4CAgAAaDAQLIAMhACADQX9HDQUMAwtBACEIDAcLQQAhAAwFCyAAQX9HDQILQQBBACgCxNOAgABBBHI2AsTTgIAACyAIQf7///8HSw0BIAgQy4CAgAAhAEEAEMuAgIAAIQMgAEF/Rg0BIANBf0YNASAAIANPDQEgAyAAayIGIAJBOGpNDQELQQBBACgCuNOAgAAgBmoiAzYCuNOAgAACQCADQQAoArzTgIAATQ0AQQAgAzYCvNOAgAALAkACQAJAAkBBACgCoNCAgAAiBEUNAEHI04CAACEDA0AgACADKAIAIgUgAygCBCIIakYNAiADKAIIIgMNAAwDCwsCQAJAQQAoApjQgIAAIgNFDQAgACADTw0BC0EAIAA2ApjQgIAAC0EAIQNBACAGNgLM04CAAEEAIAA2AsjTgIAAQQBBfzYCqNCAgABBAEEAKALg04CAADYCrNCAgABBAEEANgLU04CAAANAIANBxNCAgABqIANBuNCAgABqIgQ2AgAgBCADQbDQgIAAaiIFNgIAIANBvNCAgABqIAU2AgAgA0HM0ICAAGogA0HA0ICAAGoiBTYCACAFIAQ2AgAgA0HU0ICAAGogA0HI0ICAAGoiBDYCACAEIAU2AgAgA0HQ0ICAAGogBDYCACADQSBqIgNBgAJHDQALIABBeCAAa0EPcUEAIABBCGpBD3EbIgNqIgQgBkFIaiIFIANrIgNBAXI2AgRBAEEAKALw04CAADYCpNCAgABBACADNgKU0ICAAEEAIAQ2AqDQgIAAIAAgBWpBODYCBAwCCyADLQAMQQhxDQAgBCAFSQ0AIAQgAE8NACAEQXggBGtBD3FBACAEQQhqQQ9xGyIFaiIAQQAoApTQgIAAIAZqIgsgBWsiBUEBcjYCBCADIAggBmo2AgRBAEEAKALw04CAADYCpNCAgABBACAFNgKU0ICAAEEAIAA2AqDQgIAAIAQgC2pBODYCBAwBCwJAIABBACgCmNCAgAAiCE8NAEEAIAA2ApjQgIAAIAAhCAsgACAGaiEFQcjTgIAAIQMCQAJAAkACQAJAAkACQANAIAMoAgAgBUYNASADKAIIIgMNAAwCCwsgAy0ADEEIcUUNAQtByNOAgAAhAwNAAkAgAygCACIFIARLDQAgBSADKAIEaiIFIARLDQMLIAMoAgghAwwACwsgAyAANgIAIAMgAygCBCAGajYCBCAAQXggAGtBD3FBACAAQQhqQQ9xG2oiCyACQQNyNgIEIAVBeCAFa0EPcUEAIAVBCGpBD3EbaiIGIAsgAmoiAmshAwJAIAYgBEcNAEEAIAI2AqDQgIAAQQBBACgClNCAgAAgA2oiAzYClNCAgAAgAiADQQFyNgIEDAMLAkAgBkEAKAKc0ICAAEcNAEEAIAI2ApzQgIAAQQBBACgCkNCAgAAgA2oiAzYCkNCAgAAgAiADQQFyNgIEIAIgA2ogAzYCAAwDCwJAIAYoAgQiBEEDcUEBRw0AIARBeHEhBwJAAkAgBEH/AUsNACAGKAIIIgUgBEEDdiIIQQN0QbDQgIAAaiIARhoCQCAGKAIMIgQgBUcNAEEAQQAoAojQgIAAQX4gCHdxNgKI0ICAAAwCCyAEIABGGiAEIAU2AgggBSAENgIMDAELIAYoAhghCQJAAkAgBigCDCIAIAZGDQAgBigCCCIEIAhJGiAAIAQ2AgggBCAANgIMDAELAkAgBkEUaiIEKAIAIgUNACAGQRBqIgQoAgAiBQ0AQQAhAAwBCwNAIAQhCCAFIgBBFGoiBCgCACIFDQAgAEEQaiEEIAAoAhAiBQ0ACyAIQQA2AgALIAlFDQACQAJAIAYgBigCHCIFQQJ0QbjSgIAAaiIEKAIARw0AIAQgADYCACAADQFBAEEAKAKM0ICAAEF+IAV3cTYCjNCAgAAMAgsgCUEQQRQgCSgCECAGRhtqIAA2AgAgAEUNAQsgACAJNgIYAkAgBigCECIERQ0AIAAgBDYCECAEIAA2AhgLIAYoAhQiBEUNACAAQRRqIAQ2AgAgBCAANgIYCyAHIANqIQMgBiAHaiIGKAIEIQQLIAYgBEF+cTYCBCACIANqIAM2AgAgAiADQQFyNgIEAkAgA0H/AUsNACADQXhxQbDQgIAAaiEEAkACQEEAKAKI0ICAACIFQQEgA0EDdnQiA3ENAEEAIAUgA3I2AojQgIAAIAQhAwwBCyAEKAIIIQMLIAMgAjYCDCAEIAI2AgggAiAENgIMIAIgAzYCCAwDC0EfIQQCQCADQf///wdLDQAgA0EIdiIEIARBgP4/akEQdkEIcSIEdCIFIAVBgOAfakEQdkEEcSIFdCIAIABBgIAPakEQdkECcSIAdEEPdiAEIAVyIAByayIEQQF0IAMgBEEVanZBAXFyQRxqIQQLIAIgBDYCHCACQgA3AhAgBEECdEG40oCAAGohBQJAQQAoAozQgIAAIgBBASAEdCIIcQ0AIAUgAjYCAEEAIAAgCHI2AozQgIAAIAIgBTYCGCACIAI2AgggAiACNgIMDAMLIANBAEEZIARBAXZrIARBH0YbdCEEIAUoAgAhAANAIAAiBSgCBEF4cSADRg0CIARBHXYhACAEQQF0IQQgBSAAQQRxakEQaiIIKAIAIgANAAsgCCACNgIAIAIgBTYCGCACIAI2AgwgAiACNgIIDAILIABBeCAAa0EPcUEAIABBCGpBD3EbIgNqIgsgBkFIaiIIIANrIgNBAXI2AgQgACAIakE4NgIEIAQgBUE3IAVrQQ9xQQAgBUFJakEPcRtqQUFqIgggCCAEQRBqSRsiCEEjNgIEQQBBACgC8NOAgAA2AqTQgIAAQQAgAzYClNCAgABBACALNgKg0ICAACAIQRBqQQApAtDTgIAANwIAIAhBACkCyNOAgAA3AghBACAIQQhqNgLQ04CAAEEAIAY2AszTgIAAQQAgADYCyNOAgABBAEEANgLU04CAACAIQSRqIQMDQCADQQc2AgAgA0EEaiIDIAVJDQALIAggBEYNAyAIIAgoAgRBfnE2AgQgCCAIIARrIgA2AgAgBCAAQQFyNgIEAkAgAEH/AUsNACAAQXhxQbDQgIAAaiEDAkACQEEAKAKI0ICAACIFQQEgAEEDdnQiAHENAEEAIAUgAHI2AojQgIAAIAMhBQwBCyADKAIIIQULIAUgBDYCDCADIAQ2AgggBCADNgIMIAQgBTYCCAwEC0EfIQMCQCAAQf///wdLDQAgAEEIdiIDIANBgP4/akEQdkEIcSIDdCIFIAVBgOAfakEQdkEEcSIFdCIIIAhBgIAPakEQdkECcSIIdEEPdiADIAVyIAhyayIDQQF0IAAgA0EVanZBAXFyQRxqIQMLIAQgAzYCHCAEQgA3AhAgA0ECdEG40oCAAGohBQJAQQAoAozQgIAAIghBASADdCIGcQ0AIAUgBDYCAEEAIAggBnI2AozQgIAAIAQgBTYCGCAEIAQ2AgggBCAENgIMDAQLIABBAEEZIANBAXZrIANBH0YbdCEDIAUoAgAhCANAIAgiBSgCBEF4cSAARg0DIANBHXYhCCADQQF0IQMgBSAIQQRxakEQaiIGKAIAIggNAAsgBiAENgIAIAQgBTYCGCAEIAQ2AgwgBCAENgIIDAMLIAUoAggiAyACNgIMIAUgAjYCCCACQQA2AhggAiAFNgIMIAIgAzYCCAsgC0EIaiEDDAULIAUoAggiAyAENgIMIAUgBDYCCCAEQQA2AhggBCAFNgIMIAQgAzYCCAtBACgClNCAgAAiAyACTQ0AQQAoAqDQgIAAIgQgAmoiBSADIAJrIgNBAXI2AgRBACADNgKU0ICAAEEAIAU2AqDQgIAAIAQgAkEDcjYCBCAEQQhqIQMMAwtBACEDQQBBMDYC+NOAgAAMAgsCQCALRQ0AAkACQCAIIAgoAhwiBUECdEG40oCAAGoiAygCAEcNACADIAA2AgAgAA0BQQAgB0F+IAV3cSIHNgKM0ICAAAwCCyALQRBBFCALKAIQIAhGG2ogADYCACAARQ0BCyAAIAs2AhgCQCAIKAIQIgNFDQAgACADNgIQIAMgADYCGAsgCEEUaigCACIDRQ0AIABBFGogAzYCACADIAA2AhgLAkACQCAEQQ9LDQAgCCAEIAJqIgNBA3I2AgQgCCADaiIDIAMoAgRBAXI2AgQMAQsgCCACaiIAIARBAXI2AgQgCCACQQNyNgIEIAAgBGogBDYCAAJAIARB/wFLDQAgBEF4cUGw0ICAAGohAwJAAkBBACgCiNCAgAAiBUEBIARBA3Z0IgRxDQBBACAFIARyNgKI0ICAACADIQQMAQsgAygCCCEECyAEIAA2AgwgAyAANgIIIAAgAzYCDCAAIAQ2AggMAQtBHyEDAkAgBEH///8HSw0AIARBCHYiAyADQYD+P2pBEHZBCHEiA3QiBSAFQYDgH2pBEHZBBHEiBXQiAiACQYCAD2pBEHZBAnEiAnRBD3YgAyAFciACcmsiA0EBdCAEIANBFWp2QQFxckEcaiEDCyAAIAM2AhwgAEIANwIQIANBAnRBuNKAgABqIQUCQCAHQQEgA3QiAnENACAFIAA2AgBBACAHIAJyNgKM0ICAACAAIAU2AhggACAANgIIIAAgADYCDAwBCyAEQQBBGSADQQF2ayADQR9GG3QhAyAFKAIAIQICQANAIAIiBSgCBEF4cSAERg0BIANBHXYhAiADQQF0IQMgBSACQQRxakEQaiIGKAIAIgINAAsgBiAANgIAIAAgBTYCGCAAIAA2AgwgACAANgIIDAELIAUoAggiAyAANgIMIAUgADYCCCAAQQA2AhggACAFNgIMIAAgAzYCCAsgCEEIaiEDDAELAkAgCkUNAAJAAkAgACAAKAIcIgVBAnRBuNKAgABqIgMoAgBHDQAgAyAINgIAIAgNAUEAIAlBfiAFd3E2AozQgIAADAILIApBEEEUIAooAhAgAEYbaiAINgIAIAhFDQELIAggCjYCGAJAIAAoAhAiA0UNACAIIAM2AhAgAyAINgIYCyAAQRRqKAIAIgNFDQAgCEEUaiADNgIAIAMgCDYCGAsCQAJAIARBD0sNACAAIAQgAmoiA0EDcjYCBCAAIANqIgMgAygCBEEBcjYCBAwBCyAAIAJqIgUgBEEBcjYCBCAAIAJBA3I2AgQgBSAEaiAENgIAAkAgB0UNACAHQXhxQbDQgIAAaiECQQAoApzQgIAAIQMCQAJAQQEgB0EDdnQiCCAGcQ0AQQAgCCAGcjYCiNCAgAAgAiEIDAELIAIoAgghCAsgCCADNgIMIAIgAzYCCCADIAI2AgwgAyAINgIIC0EAIAU2ApzQgIAAQQAgBDYCkNCAgAALIABBCGohAwsgAUEQaiSAgICAACADCwoAIAAQyYCAgAAL4g0BB38CQCAARQ0AIABBeGoiASAAQXxqKAIAIgJBeHEiAGohAwJAIAJBAXENACACQQNxRQ0BIAEgASgCACICayIBQQAoApjQgIAAIgRJDQEgAiAAaiEAAkAgAUEAKAKc0ICAAEYNAAJAIAJB/wFLDQAgASgCCCIEIAJBA3YiBUEDdEGw0ICAAGoiBkYaAkAgASgCDCICIARHDQBBAEEAKAKI0ICAAEF+IAV3cTYCiNCAgAAMAwsgAiAGRhogAiAENgIIIAQgAjYCDAwCCyABKAIYIQcCQAJAIAEoAgwiBiABRg0AIAEoAggiAiAESRogBiACNgIIIAIgBjYCDAwBCwJAIAFBFGoiAigCACIEDQAgAUEQaiICKAIAIgQNAEEAIQYMAQsDQCACIQUgBCIGQRRqIgIoAgAiBA0AIAZBEGohAiAGKAIQIgQNAAsgBUEANgIACyAHRQ0BAkACQCABIAEoAhwiBEECdEG40oCAAGoiAigCAEcNACACIAY2AgAgBg0BQQBBACgCjNCAgABBfiAEd3E2AozQgIAADAMLIAdBEEEUIAcoAhAgAUYbaiAGNgIAIAZFDQILIAYgBzYCGAJAIAEoAhAiAkUNACAGIAI2AhAgAiAGNgIYCyABKAIUIgJFDQEgBkEUaiACNgIAIAIgBjYCGAwBCyADKAIEIgJBA3FBA0cNACADIAJBfnE2AgRBACAANgKQ0ICAACABIABqIAA2AgAgASAAQQFyNgIEDwsgASADTw0AIAMoAgQiAkEBcUUNAAJAAkAgAkECcQ0AAkAgA0EAKAKg0ICAAEcNAEEAIAE2AqDQgIAAQQBBACgClNCAgAAgAGoiADYClNCAgAAgASAAQQFyNgIEIAFBACgCnNCAgABHDQNBAEEANgKQ0ICAAEEAQQA2ApzQgIAADwsCQCADQQAoApzQgIAARw0AQQAgATYCnNCAgABBAEEAKAKQ0ICAACAAaiIANgKQ0ICAACABIABBAXI2AgQgASAAaiAANgIADwsgAkF4cSAAaiEAAkACQCACQf8BSw0AIAMoAggiBCACQQN2IgVBA3RBsNCAgABqIgZGGgJAIAMoAgwiAiAERw0AQQBBACgCiNCAgABBfiAFd3E2AojQgIAADAILIAIgBkYaIAIgBDYCCCAEIAI2AgwMAQsgAygCGCEHAkACQCADKAIMIgYgA0YNACADKAIIIgJBACgCmNCAgABJGiAGIAI2AgggAiAGNgIMDAELAkAgA0EUaiICKAIAIgQNACADQRBqIgIoAgAiBA0AQQAhBgwBCwNAIAIhBSAEIgZBFGoiAigCACIEDQAgBkEQaiECIAYoAhAiBA0ACyAFQQA2AgALIAdFDQACQAJAIAMgAygCHCIEQQJ0QbjSgIAAaiICKAIARw0AIAIgBjYCACAGDQFBAEEAKAKM0ICAAEF+IAR3cTYCjNCAgAAMAgsgB0EQQRQgBygCECADRhtqIAY2AgAgBkUNAQsgBiAHNgIYAkAgAygCECICRQ0AIAYgAjYCECACIAY2AhgLIAMoAhQiAkUNACAGQRRqIAI2AgAgAiAGNgIYCyABIABqIAA2AgAgASAAQQFyNgIEIAFBACgCnNCAgABHDQFBACAANgKQ0ICAAA8LIAMgAkF+cTYCBCABIABqIAA2AgAgASAAQQFyNgIECwJAIABB/wFLDQAgAEF4cUGw0ICAAGohAgJAAkBBACgCiNCAgAAiBEEBIABBA3Z0IgBxDQBBACAEIAByNgKI0ICAACACIQAMAQsgAigCCCEACyAAIAE2AgwgAiABNgIIIAEgAjYCDCABIAA2AggPC0EfIQICQCAAQf///wdLDQAgAEEIdiICIAJBgP4/akEQdkEIcSICdCIEIARBgOAfakEQdkEEcSIEdCIGIAZBgIAPakEQdkECcSIGdEEPdiACIARyIAZyayICQQF0IAAgAkEVanZBAXFyQRxqIQILIAEgAjYCHCABQgA3AhAgAkECdEG40oCAAGohBAJAAkBBACgCjNCAgAAiBkEBIAJ0IgNxDQAgBCABNgIAQQAgBiADcjYCjNCAgAAgASAENgIYIAEgATYCCCABIAE2AgwMAQsgAEEAQRkgAkEBdmsgAkEfRht0IQIgBCgCACEGAkADQCAGIgQoAgRBeHEgAEYNASACQR12IQYgAkEBdCECIAQgBkEEcWpBEGoiAygCACIGDQALIAMgATYCACABIAQ2AhggASABNgIMIAEgATYCCAwBCyAEKAIIIgAgATYCDCAEIAE2AgggAUEANgIYIAEgBDYCDCABIAA2AggLQQBBACgCqNCAgABBf2oiAUF/IAEbNgKo0ICAAAsLBAAAAAtOAAJAIAANAD8AQRB0DwsCQCAAQf//A3ENACAAQX9MDQACQCAAQRB2QAAiAEF/Rw0AQQBBMDYC+NOAgABBfw8LIABBEHQPCxDKgICAAAAL8gICA38BfgJAIAJFDQAgACABOgAAIAIgAGoiA0F/aiABOgAAIAJBA0kNACAAIAE6AAIgACABOgABIANBfWogAToAACADQX5qIAE6AAAgAkEHSQ0AIAAgAToAAyADQXxqIAE6AAAgAkEJSQ0AIABBACAAa0EDcSIEaiIDIAFB/wFxQYGChAhsIgE2AgAgAyACIARrQXxxIgRqIgJBfGogATYCACAEQQlJDQAgAyABNgIIIAMgATYCBCACQXhqIAE2AgAgAkF0aiABNgIAIARBGUkNACADIAE2AhggAyABNgIUIAMgATYCECADIAE2AgwgAkFwaiABNgIAIAJBbGogATYCACACQWhqIAE2AgAgAkFkaiABNgIAIAQgA0EEcUEYciIFayICQSBJDQAgAa1CgYCAgBB+IQYgAyAFaiEBA0AgASAGNwMYIAEgBjcDECABIAY3AwggASAGNwMAIAFBIGohASACQWBqIgJBH0sNAAsLIAALC45IAQBBgAgLhkgBAAAAAgAAAAMAAAAAAAAAAAAAAAQAAAAFAAAAAAAAAAAAAAAGAAAABwAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEludmFsaWQgY2hhciBpbiB1cmwgcXVlcnkAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9ib2R5AENvbnRlbnQtTGVuZ3RoIG92ZXJmbG93AENodW5rIHNpemUgb3ZlcmZsb3cAUmVzcG9uc2Ugb3ZlcmZsb3cASW52YWxpZCBtZXRob2QgZm9yIEhUVFAveC54IHJlcXVlc3QASW52YWxpZCBtZXRob2QgZm9yIFJUU1AveC54IHJlcXVlc3QARXhwZWN0ZWQgU09VUkNFIG1ldGhvZCBmb3IgSUNFL3gueCByZXF1ZXN0AEludmFsaWQgY2hhciBpbiB1cmwgZnJhZ21lbnQgc3RhcnQARXhwZWN0ZWQgZG90AFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25fc3RhdHVzAEludmFsaWQgcmVzcG9uc2Ugc3RhdHVzAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMAVXNlciBjYWxsYmFjayBlcnJvcgBgb25fcmVzZXRgIGNhbGxiYWNrIGVycm9yAGBvbl9jaHVua19oZWFkZXJgIGNhbGxiYWNrIGVycm9yAGBvbl9tZXNzYWdlX2JlZ2luYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfZXh0ZW5zaW9uX3ZhbHVlYCBjYWxsYmFjayBlcnJvcgBgb25fc3RhdHVzX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fdmVyc2lvbl9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX3VybF9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX2NodW5rX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25faGVhZGVyX3ZhbHVlX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fbWVzc2FnZV9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX21ldGhvZF9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX2hlYWRlcl9maWVsZF9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX2NodW5rX2V4dGVuc2lvbl9uYW1lYCBjYWxsYmFjayBlcnJvcgBVbmV4cGVjdGVkIGNoYXIgaW4gdXJsIHNlcnZlcgBJbnZhbGlkIGhlYWRlciB2YWx1ZSBjaGFyAEludmFsaWQgaGVhZGVyIGZpZWxkIGNoYXIAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl92ZXJzaW9uAEludmFsaWQgbWlub3IgdmVyc2lvbgBJbnZhbGlkIG1ham9yIHZlcnNpb24ARXhwZWN0ZWQgc3BhY2UgYWZ0ZXIgdmVyc2lvbgBFeHBlY3RlZCBDUkxGIGFmdGVyIHZlcnNpb24ASW52YWxpZCBIVFRQIHZlcnNpb24ASW52YWxpZCBoZWFkZXIgdG9rZW4AU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl91cmwASW52YWxpZCBjaGFyYWN0ZXJzIGluIHVybABVbmV4cGVjdGVkIHN0YXJ0IGNoYXIgaW4gdXJsAERvdWJsZSBAIGluIHVybABFbXB0eSBDb250ZW50LUxlbmd0aABJbnZhbGlkIGNoYXJhY3RlciBpbiBDb250ZW50LUxlbmd0aABEdXBsaWNhdGUgQ29udGVudC1MZW5ndGgASW52YWxpZCBjaGFyIGluIHVybCBwYXRoAENvbnRlbnQtTGVuZ3RoIGNhbid0IGJlIHByZXNlbnQgd2l0aCBUcmFuc2Zlci1FbmNvZGluZwBJbnZhbGlkIGNoYXJhY3RlciBpbiBjaHVuayBzaXplAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25faGVhZGVyX3ZhbHVlAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25fY2h1bmtfZXh0ZW5zaW9uX3ZhbHVlAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMgdmFsdWUATWlzc2luZyBleHBlY3RlZCBMRiBhZnRlciBoZWFkZXIgdmFsdWUASW52YWxpZCBgVHJhbnNmZXItRW5jb2RpbmdgIGhlYWRlciB2YWx1ZQBJbnZhbGlkIGNoYXJhY3RlciBpbiBjaHVuayBleHRlbnNpb25zIHF1b3RlIHZhbHVlAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMgcXVvdGVkIHZhbHVlAFBhdXNlZCBieSBvbl9oZWFkZXJzX2NvbXBsZXRlAEludmFsaWQgRU9GIHN0YXRlAG9uX3Jlc2V0IHBhdXNlAG9uX2NodW5rX2hlYWRlciBwYXVzZQBvbl9tZXNzYWdlX2JlZ2luIHBhdXNlAG9uX2NodW5rX2V4dGVuc2lvbl92YWx1ZSBwYXVzZQBvbl9zdGF0dXNfY29tcGxldGUgcGF1c2UAb25fdmVyc2lvbl9jb21wbGV0ZSBwYXVzZQBvbl91cmxfY29tcGxldGUgcGF1c2UAb25fY2h1bmtfY29tcGxldGUgcGF1c2UAb25faGVhZGVyX3ZhbHVlX2NvbXBsZXRlIHBhdXNlAG9uX21lc3NhZ2VfY29tcGxldGUgcGF1c2UAb25fbWV0aG9kX2NvbXBsZXRlIHBhdXNlAG9uX2hlYWRlcl9maWVsZF9jb21wbGV0ZSBwYXVzZQBvbl9jaHVua19leHRlbnNpb25fbmFtZSBwYXVzZQBVbmV4cGVjdGVkIHNwYWNlIGFmdGVyIHN0YXJ0IGxpbmUAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9jaHVua19leHRlbnNpb25fbmFtZQBJbnZhbGlkIGNoYXJhY3RlciBpbiBjaHVuayBleHRlbnNpb25zIG5hbWUAUGF1c2Ugb24gQ09OTkVDVC9VcGdyYWRlAFBhdXNlIG9uIFBSSS9VcGdyYWRlAEV4cGVjdGVkIEhUVFAvMiBDb25uZWN0aW9uIFByZWZhY2UAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9tZXRob2QARXhwZWN0ZWQgc3BhY2UgYWZ0ZXIgbWV0aG9kAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25faGVhZGVyX2ZpZWxkAFBhdXNlZABJbnZhbGlkIHdvcmQgZW5jb3VudGVyZWQASW52YWxpZCBtZXRob2QgZW5jb3VudGVyZWQAVW5leHBlY3RlZCBjaGFyIGluIHVybCBzY2hlbWEAUmVxdWVzdCBoYXMgaW52YWxpZCBgVHJhbnNmZXItRW5jb2RpbmdgAFNXSVRDSF9QUk9YWQBVU0VfUFJPWFkATUtBQ1RJVklUWQBVTlBST0NFU1NBQkxFX0VOVElUWQBDT1BZAE1PVkVEX1BFUk1BTkVOVExZAFRPT19FQVJMWQBOT1RJRlkARkFJTEVEX0RFUEVOREVOQ1kAQkFEX0dBVEVXQVkAUExBWQBQVVQAQ0hFQ0tPVVQAR0FURVdBWV9USU1FT1VUAFJFUVVFU1RfVElNRU9VVABORVRXT1JLX0NPTk5FQ1RfVElNRU9VVABDT05ORUNUSU9OX1RJTUVPVVQATE9HSU5fVElNRU9VVABORVRXT1JLX1JFQURfVElNRU9VVABQT1NUAE1JU0RJUkVDVEVEX1JFUVVFU1QAQ0xJRU5UX0NMT1NFRF9SRVFVRVNUAENMSUVOVF9DTE9TRURfTE9BRF9CQUxBTkNFRF9SRVFVRVNUAEJBRF9SRVFVRVNUAEhUVFBfUkVRVUVTVF9TRU5UX1RPX0hUVFBTX1BPUlQAUkVQT1JUAElNX0FfVEVBUE9UAFJFU0VUX0NPTlRFTlQATk9fQ09OVEVOVABQQVJUSUFMX0NPTlRFTlQASFBFX0lOVkFMSURfQ09OU1RBTlQASFBFX0NCX1JFU0VUAEdFVABIUEVfU1RSSUNUAENPTkZMSUNUAFRFTVBPUkFSWV9SRURJUkVDVABQRVJNQU5FTlRfUkVESVJFQ1QAQ09OTkVDVABNVUxUSV9TVEFUVVMASFBFX0lOVkFMSURfU1RBVFVTAFRPT19NQU5ZX1JFUVVFU1RTAEVBUkxZX0hJTlRTAFVOQVZBSUxBQkxFX0ZPUl9MRUdBTF9SRUFTT05TAE9QVElPTlMAU1dJVENISU5HX1BST1RPQ09MUwBWQVJJQU5UX0FMU09fTkVHT1RJQVRFUwBNVUxUSVBMRV9DSE9JQ0VTAElOVEVSTkFMX1NFUlZFUl9FUlJPUgBXRUJfU0VSVkVSX1VOS05PV05fRVJST1IAUkFJTEdVTl9FUlJPUgBJREVOVElUWV9QUk9WSURFUl9BVVRIRU5USUNBVElPTl9FUlJPUgBTU0xfQ0VSVElGSUNBVEVfRVJST1IASU5WQUxJRF9YX0ZPUldBUkRFRF9GT1IAU0VUX1BBUkFNRVRFUgBHRVRfUEFSQU1FVEVSAEhQRV9VU0VSAFNFRV9PVEhFUgBIUEVfQ0JfQ0hVTktfSEVBREVSAE1LQ0FMRU5EQVIAU0VUVVAAV0VCX1NFUlZFUl9JU19ET1dOAFRFQVJET1dOAEhQRV9DTE9TRURfQ09OTkVDVElPTgBIRVVSSVNUSUNfRVhQSVJBVElPTgBESVNDT05ORUNURURfT1BFUkFUSU9OAE5PTl9BVVRIT1JJVEFUSVZFX0lORk9STUFUSU9OAEhQRV9JTlZBTElEX1ZFUlNJT04ASFBFX0NCX01FU1NBR0VfQkVHSU4AU0lURV9JU19GUk9aRU4ASFBFX0lOVkFMSURfSEVBREVSX1RPS0VOAElOVkFMSURfVE9LRU4ARk9SQklEREVOAEVOSEFOQ0VfWU9VUl9DQUxNAEhQRV9JTlZBTElEX1VSTABCTE9DS0VEX0JZX1BBUkVOVEFMX0NPTlRST0wATUtDT0wAQUNMAEhQRV9JTlRFUk5BTABSRVFVRVNUX0hFQURFUl9GSUVMRFNfVE9PX0xBUkdFX1VOT0ZGSUNJQUwASFBFX09LAFVOTElOSwBVTkxPQ0sAUFJJAFJFVFJZX1dJVEgASFBFX0lOVkFMSURfQ09OVEVOVF9MRU5HVEgASFBFX1VORVhQRUNURURfQ09OVEVOVF9MRU5HVEgARkxVU0gAUFJPUFBBVENIAE0tU0VBUkNIAFVSSV9UT09fTE9ORwBQUk9DRVNTSU5HAE1JU0NFTExBTkVPVVNfUEVSU0lTVEVOVF9XQVJOSU5HAE1JU0NFTExBTkVPVVNfV0FSTklORwBIUEVfSU5WQUxJRF9UUkFOU0ZFUl9FTkNPRElORwBFeHBlY3RlZCBDUkxGAEhQRV9JTlZBTElEX0NIVU5LX1NJWkUATU9WRQBDT05USU5VRQBIUEVfQ0JfU1RBVFVTX0NPTVBMRVRFAEhQRV9DQl9IRUFERVJTX0NPTVBMRVRFAEhQRV9DQl9WRVJTSU9OX0NPTVBMRVRFAEhQRV9DQl9VUkxfQ09NUExFVEUASFBFX0NCX0NIVU5LX0NPTVBMRVRFAEhQRV9DQl9IRUFERVJfVkFMVUVfQ09NUExFVEUASFBFX0NCX0NIVU5LX0VYVEVOU0lPTl9WQUxVRV9DT01QTEVURQBIUEVfQ0JfQ0hVTktfRVhURU5TSU9OX05BTUVfQ09NUExFVEUASFBFX0NCX01FU1NBR0VfQ09NUExFVEUASFBFX0NCX01FVEhPRF9DT01QTEVURQBIUEVfQ0JfSEVBREVSX0ZJRUxEX0NPTVBMRVRFAERFTEVURQBIUEVfSU5WQUxJRF9FT0ZfU1RBVEUASU5WQUxJRF9TU0xfQ0VSVElGSUNBVEUAUEFVU0UATk9fUkVTUE9OU0UAVU5TVVBQT1JURURfTUVESUFfVFlQRQBHT05FAE5PVF9BQ0NFUFRBQkxFAFNFUlZJQ0VfVU5BVkFJTEFCTEUAUkFOR0VfTk9UX1NBVElTRklBQkxFAE9SSUdJTl9JU19VTlJFQUNIQUJMRQBSRVNQT05TRV9JU19TVEFMRQBQVVJHRQBNRVJHRQBSRVFVRVNUX0hFQURFUl9GSUVMRFNfVE9PX0xBUkdFAFJFUVVFU1RfSEVBREVSX1RPT19MQVJHRQBQQVlMT0FEX1RPT19MQVJHRQBJTlNVRkZJQ0lFTlRfU1RPUkFHRQBIUEVfUEFVU0VEX1VQR1JBREUASFBFX1BBVVNFRF9IMl9VUEdSQURFAFNPVVJDRQBBTk5PVU5DRQBUUkFDRQBIUEVfVU5FWFBFQ1RFRF9TUEFDRQBERVNDUklCRQBVTlNVQlNDUklCRQBSRUNPUkQASFBFX0lOVkFMSURfTUVUSE9EAE5PVF9GT1VORABQUk9QRklORABVTkJJTkQAUkVCSU5EAFVOQVVUSE9SSVpFRABNRVRIT0RfTk9UX0FMTE9XRUQASFRUUF9WRVJTSU9OX05PVF9TVVBQT1JURUQAQUxSRUFEWV9SRVBPUlRFRABBQ0NFUFRFRABOT1RfSU1QTEVNRU5URUQATE9PUF9ERVRFQ1RFRABIUEVfQ1JfRVhQRUNURUQASFBFX0xGX0VYUEVDVEVEAENSRUFURUQASU1fVVNFRABIUEVfUEFVU0VEAFRJTUVPVVRfT0NDVVJFRABQQVlNRU5UX1JFUVVJUkVEAFBSRUNPTkRJVElPTl9SRVFVSVJFRABQUk9YWV9BVVRIRU5USUNBVElPTl9SRVFVSVJFRABORVRXT1JLX0FVVEhFTlRJQ0FUSU9OX1JFUVVJUkVEAExFTkdUSF9SRVFVSVJFRABTU0xfQ0VSVElGSUNBVEVfUkVRVUlSRUQAVVBHUkFERV9SRVFVSVJFRABQQUdFX0VYUElSRUQAUFJFQ09ORElUSU9OX0ZBSUxFRABFWFBFQ1RBVElPTl9GQUlMRUQAUkVWQUxJREFUSU9OX0ZBSUxFRABTU0xfSEFORFNIQUtFX0ZBSUxFRABMT0NLRUQAVFJBTlNGT1JNQVRJT05fQVBQTElFRABOT1RfTU9ESUZJRUQATk9UX0VYVEVOREVEAEJBTkRXSURUSF9MSU1JVF9FWENFRURFRABTSVRFX0lTX09WRVJMT0FERUQASEVBRABFeHBlY3RlZCBIVFRQLwAAXhMAACYTAAAwEAAA8BcAAJ0TAAAVEgAAORcAAPASAAAKEAAAdRIAAK0SAACCEwAATxQAAH8QAACgFQAAIxQAAIkSAACLFAAATRUAANQRAADPFAAAEBgAAMkWAADcFgAAwREAAOAXAAC7FAAAdBQAAHwVAADlFAAACBcAAB8QAABlFQAAoxQAACgVAAACFQAAmRUAACwQAACLGQAATw8AANQOAABqEAAAzhAAAAIXAACJDgAAbhMAABwTAABmFAAAVhcAAMETAADNEwAAbBMAAGgXAABmFwAAXxcAACITAADODwAAaQ4AANgOAABjFgAAyxMAAKoOAAAoFwAAJhcAAMUTAABdFgAA6BEAAGcTAABlEwAA8hYAAHMTAAAdFwAA+RYAAPMRAADPDgAAzhUAAAwSAACzEQAApREAAGEQAAAyFwAAuxMAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQIBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIDAgICAgIAAAICAAICAAICAgICAgICAgIABAAAAAAAAgICAgICAgICAgICAgICAgICAgICAgICAgIAAAACAgICAgICAgICAgICAgICAgICAgICAgICAgICAgACAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAACAAICAgICAAACAgACAgACAgICAgICAgICAAMABAAAAAICAgICAgICAgICAgICAgICAgICAgICAgICAAAAAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAAgACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbG9zZWVlcC1hbGl2ZQAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQIBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBY2h1bmtlZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEAAQEBAQEAAAEBAAEBAAEBAQEBAQEBAQEAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABlY3Rpb25lbnQtbGVuZ3Rob25yb3h5LWNvbm5lY3Rpb24AAAAAAAAAAAAAAAAAAAByYW5zZmVyLWVuY29kaW5ncGdyYWRlDQoNCg0KU00NCg0KVFRQL0NFL1RTUC8AAAAAAAAAAAAAAAABAgABAwAAAAAAAAAAAAAAAAAAAAAAAAQBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAQIAAQMAAAAAAAAAAAAAAAAAAAAAAAAEAQEFAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAEAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAQAAAgAAAAAAAAAAAAAAAAAAAAAAAAMEAAAEBAQEBAQEBAQEBAUEBAQEBAQEBAQEBAQABAAGBwQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEAAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAEAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwAAAAAAAAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAABAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAIAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAAAAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABOT1VOQ0VFQ0tPVVRORUNURVRFQ1JJQkVMVVNIRVRFQURTRUFSQ0hSR0VDVElWSVRZTEVOREFSVkVPVElGWVBUSU9OU0NIU0VBWVNUQVRDSEdFT1JESVJFQ1RPUlRSQ0hQQVJBTUVURVJVUkNFQlNDUklCRUFSRE9XTkFDRUlORE5LQ0tVQlNDUklCRUhUVFAvQURUUC8=' + + +/***/ }), + +/***/ 449: +/***/ ((module) => { + +module.exports = 'AGFzbQEAAAABMAhgAX8Bf2ADf39/AX9gBH9/f38Bf2AAAGADf39/AGABfwBgAn9/AGAGf39/f39/AALLAQgDZW52GHdhc21fb25faGVhZGVyc19jb21wbGV0ZQACA2VudhV3YXNtX29uX21lc3NhZ2VfYmVnaW4AAANlbnYLd2FzbV9vbl91cmwAAQNlbnYOd2FzbV9vbl9zdGF0dXMAAQNlbnYUd2FzbV9vbl9oZWFkZXJfZmllbGQAAQNlbnYUd2FzbV9vbl9oZWFkZXJfdmFsdWUAAQNlbnYMd2FzbV9vbl9ib2R5AAEDZW52GHdhc21fb25fbWVzc2FnZV9jb21wbGV0ZQAAA0ZFAwMEAAAFAAAAAAAABQEFAAUFBQAABgAAAAAGBgYGAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAAABAQcAAAUFAwABBAUBcAESEgUDAQACBggBfwFBgNQECwfRBSIGbWVtb3J5AgALX2luaXRpYWxpemUACRlfX2luZGlyZWN0X2Z1bmN0aW9uX3RhYmxlAQALbGxodHRwX2luaXQAChhsbGh0dHBfc2hvdWxkX2tlZXBfYWxpdmUAQQxsbGh0dHBfYWxsb2MADAZtYWxsb2MARgtsbGh0dHBfZnJlZQANBGZyZWUASA9sbGh0dHBfZ2V0X3R5cGUADhVsbGh0dHBfZ2V0X2h0dHBfbWFqb3IADxVsbGh0dHBfZ2V0X2h0dHBfbWlub3IAEBFsbGh0dHBfZ2V0X21ldGhvZAARFmxsaHR0cF9nZXRfc3RhdHVzX2NvZGUAEhJsbGh0dHBfZ2V0X3VwZ3JhZGUAEwxsbGh0dHBfcmVzZXQAFA5sbGh0dHBfZXhlY3V0ZQAVFGxsaHR0cF9zZXR0aW5nc19pbml0ABYNbGxodHRwX2ZpbmlzaAAXDGxsaHR0cF9wYXVzZQAYDWxsaHR0cF9yZXN1bWUAGRtsbGh0dHBfcmVzdW1lX2FmdGVyX3VwZ3JhZGUAGhBsbGh0dHBfZ2V0X2Vycm5vABsXbGxodHRwX2dldF9lcnJvcl9yZWFzb24AHBdsbGh0dHBfc2V0X2Vycm9yX3JlYXNvbgAdFGxsaHR0cF9nZXRfZXJyb3JfcG9zAB4RbGxodHRwX2Vycm5vX25hbWUAHxJsbGh0dHBfbWV0aG9kX25hbWUAIBJsbGh0dHBfc3RhdHVzX25hbWUAIRpsbGh0dHBfc2V0X2xlbmllbnRfaGVhZGVycwAiIWxsaHR0cF9zZXRfbGVuaWVudF9jaHVua2VkX2xlbmd0aAAjHWxsaHR0cF9zZXRfbGVuaWVudF9rZWVwX2FsaXZlACQkbGxodHRwX3NldF9sZW5pZW50X3RyYW5zZmVyX2VuY29kaW5nACUYbGxodHRwX21lc3NhZ2VfbmVlZHNfZW9mAD8JFwEAQQELEQECAwQFCwYHNTk3MS8tJyspCrLgAkUCAAsIABCIgICAAAsZACAAEMKAgIAAGiAAIAI2AjggACABOgAoCxwAIAAgAC8BMiAALQAuIAAQwYCAgAAQgICAgAALKgEBf0HAABDGgICAACIBEMKAgIAAGiABQYCIgIAANgI4IAEgADoAKCABCwoAIAAQyICAgAALBwAgAC0AKAsHACAALQAqCwcAIAAtACsLBwAgAC0AKQsHACAALwEyCwcAIAAtAC4LRQEEfyAAKAIYIQEgAC0ALSECIAAtACghAyAAKAI4IQQgABDCgICAABogACAENgI4IAAgAzoAKCAAIAI6AC0gACABNgIYCxEAIAAgASABIAJqEMOAgIAACxAAIABBAEHcABDMgICAABoLZwEBf0EAIQECQCAAKAIMDQACQAJAAkACQCAALQAvDgMBAAMCCyAAKAI4IgFFDQAgASgCLCIBRQ0AIAAgARGAgICAAAAiAQ0DC0EADwsQyoCAgAAACyAAQcOWgIAANgIQQQ4hAQsgAQseAAJAIAAoAgwNACAAQdGbgIAANgIQIABBFTYCDAsLFgACQCAAKAIMQRVHDQAgAEEANgIMCwsWAAJAIAAoAgxBFkcNACAAQQA2AgwLCwcAIAAoAgwLBwAgACgCEAsJACAAIAE2AhALBwAgACgCFAsiAAJAIABBJEkNABDKgICAAAALIABBAnRBoLOAgABqKAIACyIAAkAgAEEuSQ0AEMqAgIAAAAsgAEECdEGwtICAAGooAgAL7gsBAX9B66iAgAAhAQJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAIABBnH9qDvQDY2IAAWFhYWFhYQIDBAVhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhBgcICQoLDA0OD2FhYWFhEGFhYWFhYWFhYWFhEWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYRITFBUWFxgZGhthYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhHB0eHyAhIiMkJSYnKCkqKywtLi8wMTIzNDU2YTc4OTphYWFhYWFhYTthYWE8YWFhYT0+P2FhYWFhYWFhQGFhQWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYUJDREVGR0hJSktMTU5PUFFSU2FhYWFhYWFhVFVWV1hZWlthXF1hYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFeYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhX2BhC0Hhp4CAAA8LQaShgIAADwtBy6yAgAAPC0H+sYCAAA8LQcCkgIAADwtBq6SAgAAPC0GNqICAAA8LQeKmgIAADwtBgLCAgAAPC0G5r4CAAA8LQdekgIAADwtB75+AgAAPC0Hhn4CAAA8LQfqfgIAADwtB8qCAgAAPC0Gor4CAAA8LQa6ygIAADwtBiLCAgAAPC0Hsp4CAAA8LQYKigIAADwtBjp2AgAAPC0HQroCAAA8LQcqjgIAADwtBxbKAgAAPC0HfnICAAA8LQdKcgIAADwtBxKCAgAAPC0HXoICAAA8LQaKfgIAADwtB7a6AgAAPC0GrsICAAA8LQdSlgIAADwtBzK6AgAAPC0H6roCAAA8LQfyrgIAADwtB0rCAgAAPC0HxnYCAAA8LQbuggIAADwtB96uAgAAPC0GQsYCAAA8LQdexgIAADwtBoq2AgAAPC0HUp4CAAA8LQeCrgIAADwtBn6yAgAAPC0HrsYCAAA8LQdWfgIAADwtByrGAgAAPC0HepYCAAA8LQdSegIAADwtB9JyAgAAPC0GnsoCAAA8LQbGdgIAADwtBoJ2AgAAPC0G5sYCAAA8LQbywgIAADwtBkqGAgAAPC0GzpoCAAA8LQemsgIAADwtBrJ6AgAAPC0HUq4CAAA8LQfemgIAADwtBgKaAgAAPC0GwoYCAAA8LQf6egIAADwtBjaOAgAAPC0GJrYCAAA8LQfeigIAADwtBoLGAgAAPC0Gun4CAAA8LQcalgIAADwtB6J6AgAAPC0GTooCAAA8LQcKvgIAADwtBw52AgAAPC0GLrICAAA8LQeGdgIAADwtBja+AgAAPC0HqoYCAAA8LQbStgIAADwtB0q+AgAAPC0HfsoCAAA8LQdKygIAADwtB8LCAgAAPC0GpooCAAA8LQfmjgIAADwtBmZ6AgAAPC0G1rICAAA8LQZuwgIAADwtBkrKAgAAPC0G2q4CAAA8LQcKigIAADwtB+LKAgAAPC0GepYCAAA8LQdCigIAADwtBup6AgAAPC0GBnoCAAA8LEMqAgIAAAAtB1qGAgAAhAQsgAQsWACAAIAAtAC1B/gFxIAFBAEdyOgAtCxkAIAAgAC0ALUH9AXEgAUEAR0EBdHI6AC0LGQAgACAALQAtQfsBcSABQQBHQQJ0cjoALQsZACAAIAAtAC1B9wFxIAFBAEdBA3RyOgAtCy4BAn9BACEDAkAgACgCOCIERQ0AIAQoAgAiBEUNACAAIAQRgICAgAAAIQMLIAMLSQECf0EAIQMCQCAAKAI4IgRFDQAgBCgCBCIERQ0AIAAgASACIAFrIAQRgYCAgAAAIgNBf0cNACAAQcaRgIAANgIQQRghAwsgAwsuAQJ/QQAhAwJAIAAoAjgiBEUNACAEKAIwIgRFDQAgACAEEYCAgIAAACEDCyADC0kBAn9BACEDAkAgACgCOCIERQ0AIAQoAggiBEUNACAAIAEgAiABayAEEYGAgIAAACIDQX9HDQAgAEH2ioCAADYCEEEYIQMLIAMLLgECf0EAIQMCQCAAKAI4IgRFDQAgBCgCNCIERQ0AIAAgBBGAgICAAAAhAwsgAwtJAQJ/QQAhAwJAIAAoAjgiBEUNACAEKAIMIgRFDQAgACABIAIgAWsgBBGBgICAAAAiA0F/Rw0AIABB7ZqAgAA2AhBBGCEDCyADCy4BAn9BACEDAkAgACgCOCIERQ0AIAQoAjgiBEUNACAAIAQRgICAgAAAIQMLIAMLSQECf0EAIQMCQCAAKAI4IgRFDQAgBCgCECIERQ0AIAAgASACIAFrIAQRgYCAgAAAIgNBf0cNACAAQZWQgIAANgIQQRghAwsgAwsuAQJ/QQAhAwJAIAAoAjgiBEUNACAEKAI8IgRFDQAgACAEEYCAgIAAACEDCyADC0kBAn9BACEDAkAgACgCOCIERQ0AIAQoAhQiBEUNACAAIAEgAiABayAEEYGAgIAAACIDQX9HDQAgAEGqm4CAADYCEEEYIQMLIAMLLgECf0EAIQMCQCAAKAI4IgRFDQAgBCgCQCIERQ0AIAAgBBGAgICAAAAhAwsgAwtJAQJ/QQAhAwJAIAAoAjgiBEUNACAEKAIYIgRFDQAgACABIAIgAWsgBBGBgICAAAAiA0F/Rw0AIABB7ZOAgAA2AhBBGCEDCyADCy4BAn9BACEDAkAgACgCOCIERQ0AIAQoAkQiBEUNACAAIAQRgICAgAAAIQMLIAMLLgECf0EAIQMCQCAAKAI4IgRFDQAgBCgCJCIERQ0AIAAgBBGAgICAAAAhAwsgAwsuAQJ/QQAhAwJAIAAoAjgiBEUNACAEKAIsIgRFDQAgACAEEYCAgIAAACEDCyADC0kBAn9BACEDAkAgACgCOCIERQ0AIAQoAigiBEUNACAAIAEgAiABayAEEYGAgIAAACIDQX9HDQAgAEH2iICAADYCEEEYIQMLIAMLLgECf0EAIQMCQCAAKAI4IgRFDQAgBCgCUCIERQ0AIAAgBBGAgICAAAAhAwsgAwtJAQJ/QQAhAwJAIAAoAjgiBEUNACAEKAIcIgRFDQAgACABIAIgAWsgBBGBgICAAAAiA0F/Rw0AIABBwpmAgAA2AhBBGCEDCyADCy4BAn9BACEDAkAgACgCOCIERQ0AIAQoAkgiBEUNACAAIAQRgICAgAAAIQMLIAMLSQECf0EAIQMCQCAAKAI4IgRFDQAgBCgCICIERQ0AIAAgASACIAFrIAQRgYCAgAAAIgNBf0cNACAAQZSUgIAANgIQQRghAwsgAwsuAQJ/QQAhAwJAIAAoAjgiBEUNACAEKAJMIgRFDQAgACAEEYCAgIAAACEDCyADCy4BAn9BACEDAkAgACgCOCIERQ0AIAQoAlQiBEUNACAAIAQRgICAgAAAIQMLIAMLLgECf0EAIQMCQCAAKAI4IgRFDQAgBCgCWCIERQ0AIAAgBBGAgICAAAAhAwsgAwtFAQF/AkACQCAALwEwQRRxQRRHDQBBASEDIAAtAChBAUYNASAALwEyQeUARiEDDAELIAAtAClBBUYhAwsgACADOgAuQQAL/gEBA39BASEDAkAgAC8BMCIEQQhxDQAgACkDIEIAUiEDCwJAAkAgAC0ALkUNAEEBIQUgAC0AKUEFRg0BQQEhBSAEQcAAcUUgA3FBAUcNAQtBACEFIARBwABxDQBBAiEFIARB//8DcSIDQQhxDQACQCADQYAEcUUNAAJAIAAtAChBAUcNACAALQAtQQpxDQBBBQ8LQQQPCwJAIANBIHENAAJAIAAtAChBAUYNACAALwEyQf//A3EiAEGcf2pB5ABJDQAgAEHMAUYNACAAQbACRg0AQQQhBSAEQShxRQ0CIANBiARxQYAERg0CC0EADwtBAEEDIAApAyBQGyEFCyAFC2IBAn9BACEBAkAgAC0AKEEBRg0AIAAvATJB//8DcSICQZx/akHkAEkNACACQcwBRg0AIAJBsAJGDQAgAC8BMCIAQcAAcQ0AQQEhASAAQYgEcUGABEYNACAAQShxRSEBCyABC6cBAQN/AkACQAJAIAAtACpFDQAgAC0AK0UNAEEAIQMgAC8BMCIEQQJxRQ0BDAILQQAhAyAALwEwIgRBAXFFDQELQQEhAyAALQAoQQFGDQAgAC8BMkH//wNxIgVBnH9qQeQASQ0AIAVBzAFGDQAgBUGwAkYNACAEQcAAcQ0AQQAhAyAEQYgEcUGABEYNACAEQShxQQBHIQMLIABBADsBMCAAQQA6AC8gAwuZAQECfwJAAkACQCAALQAqRQ0AIAAtACtFDQBBACEBIAAvATAiAkECcUUNAQwCC0EAIQEgAC8BMCICQQFxRQ0BC0EBIQEgAC0AKEEBRg0AIAAvATJB//8DcSIAQZx/akHkAEkNACAAQcwBRg0AIABBsAJGDQAgAkHAAHENAEEAIQEgAkGIBHFBgARGDQAgAkEocUEARyEBCyABC0kBAXsgAEEQav0MAAAAAAAAAAAAAAAAAAAAACIB/QsDACAAIAH9CwMAIABBMGogAf0LAwAgAEEgaiAB/QsDACAAQd0BNgIcQQALewEBfwJAIAAoAgwiAw0AAkAgACgCBEUNACAAIAE2AgQLAkAgACABIAIQxICAgAAiAw0AIAAoAgwPCyAAIAM2AhxBACEDIAAoAgQiAUUNACAAIAEgAiAAKAIIEYGAgIAAACIBRQ0AIAAgAjYCFCAAIAE2AgwgASEDCyADC+TzAQMOfwN+BH8jgICAgABBEGsiAySAgICAACABIQQgASEFIAEhBiABIQcgASEIIAEhCSABIQogASELIAEhDCABIQ0gASEOIAEhDwJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQCAAKAIcIhBBf2oO3QHaAQHZAQIDBAUGBwgJCgsMDQ7YAQ8Q1wEREtYBExQVFhcYGRob4AHfARwdHtUBHyAhIiMkJdQBJicoKSorLNMB0gEtLtEB0AEvMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUbbAUdISUrPAc4BS80BTMwBTU5PUFFSU1RVVldYWVpbXF1eX2BhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ent8fX5/gAGBAYIBgwGEAYUBhgGHAYgBiQGKAYsBjAGNAY4BjwGQAZEBkgGTAZQBlQGWAZcBmAGZAZoBmwGcAZ0BngGfAaABoQGiAaMBpAGlAaYBpwGoAakBqgGrAawBrQGuAa8BsAGxAbIBswG0AbUBtgG3AcsBygG4AckBuQHIAboBuwG8Ab0BvgG/AcABwQHCAcMBxAHFAcYBANwBC0EAIRAMxgELQQ4hEAzFAQtBDSEQDMQBC0EPIRAMwwELQRAhEAzCAQtBEyEQDMEBC0EUIRAMwAELQRUhEAy/AQtBFiEQDL4BC0EXIRAMvQELQRghEAy8AQtBGSEQDLsBC0EaIRAMugELQRshEAy5AQtBHCEQDLgBC0EIIRAMtwELQR0hEAy2AQtBICEQDLUBC0EfIRAMtAELQQchEAyzAQtBISEQDLIBC0EiIRAMsQELQR4hEAywAQtBIyEQDK8BC0ESIRAMrgELQREhEAytAQtBJCEQDKwBC0ElIRAMqwELQSYhEAyqAQtBJyEQDKkBC0HDASEQDKgBC0EpIRAMpwELQSshEAymAQtBLCEQDKUBC0EtIRAMpAELQS4hEAyjAQtBLyEQDKIBC0HEASEQDKEBC0EwIRAMoAELQTQhEAyfAQtBDCEQDJ4BC0ExIRAMnQELQTIhEAycAQtBMyEQDJsBC0E5IRAMmgELQTUhEAyZAQtBxQEhEAyYAQtBCyEQDJcBC0E6IRAMlgELQTYhEAyVAQtBCiEQDJQBC0E3IRAMkwELQTghEAySAQtBPCEQDJEBC0E7IRAMkAELQT0hEAyPAQtBCSEQDI4BC0EoIRAMjQELQT4hEAyMAQtBPyEQDIsBC0HAACEQDIoBC0HBACEQDIkBC0HCACEQDIgBC0HDACEQDIcBC0HEACEQDIYBC0HFACEQDIUBC0HGACEQDIQBC0EqIRAMgwELQccAIRAMggELQcgAIRAMgQELQckAIRAMgAELQcoAIRAMfwtBywAhEAx+C0HNACEQDH0LQcwAIRAMfAtBzgAhEAx7C0HPACEQDHoLQdAAIRAMeQtB0QAhEAx4C0HSACEQDHcLQdMAIRAMdgtB1AAhEAx1C0HWACEQDHQLQdUAIRAMcwtBBiEQDHILQdcAIRAMcQtBBSEQDHALQdgAIRAMbwtBBCEQDG4LQdkAIRAMbQtB2gAhEAxsC0HbACEQDGsLQdwAIRAMagtBAyEQDGkLQd0AIRAMaAtB3gAhEAxnC0HfACEQDGYLQeEAIRAMZQtB4AAhEAxkC0HiACEQDGMLQeMAIRAMYgtBAiEQDGELQeQAIRAMYAtB5QAhEAxfC0HmACEQDF4LQecAIRAMXQtB6AAhEAxcC0HpACEQDFsLQeoAIRAMWgtB6wAhEAxZC0HsACEQDFgLQe0AIRAMVwtB7gAhEAxWC0HvACEQDFULQfAAIRAMVAtB8QAhEAxTC0HyACEQDFILQfMAIRAMUQtB9AAhEAxQC0H1ACEQDE8LQfYAIRAMTgtB9wAhEAxNC0H4ACEQDEwLQfkAIRAMSwtB+gAhEAxKC0H7ACEQDEkLQfwAIRAMSAtB/QAhEAxHC0H+ACEQDEYLQf8AIRAMRQtBgAEhEAxEC0GBASEQDEMLQYIBIRAMQgtBgwEhEAxBC0GEASEQDEALQYUBIRAMPwtBhgEhEAw+C0GHASEQDD0LQYgBIRAMPAtBiQEhEAw7C0GKASEQDDoLQYsBIRAMOQtBjAEhEAw4C0GNASEQDDcLQY4BIRAMNgtBjwEhEAw1C0GQASEQDDQLQZEBIRAMMwtBkgEhEAwyC0GTASEQDDELQZQBIRAMMAtBlQEhEAwvC0GWASEQDC4LQZcBIRAMLQtBmAEhEAwsC0GZASEQDCsLQZoBIRAMKgtBmwEhEAwpC0GcASEQDCgLQZ0BIRAMJwtBngEhEAwmC0GfASEQDCULQaABIRAMJAtBoQEhEAwjC0GiASEQDCILQaMBIRAMIQtBpAEhEAwgC0GlASEQDB8LQaYBIRAMHgtBpwEhEAwdC0GoASEQDBwLQakBIRAMGwtBqgEhEAwaC0GrASEQDBkLQawBIRAMGAtBrQEhEAwXC0GuASEQDBYLQQEhEAwVC0GvASEQDBQLQbABIRAMEwtBsQEhEAwSC0GzASEQDBELQbIBIRAMEAtBtAEhEAwPC0G1ASEQDA4LQbYBIRAMDQtBtwEhEAwMC0G4ASEQDAsLQbkBIRAMCgtBugEhEAwJC0G7ASEQDAgLQcYBIRAMBwtBvAEhEAwGC0G9ASEQDAULQb4BIRAMBAtBvwEhEAwDC0HAASEQDAILQcIBIRAMAQtBwQEhEAsDQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAIBAOxwEAAQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB4fICEjJSg/QEFERUZHSElKS0xNT1BRUlPeA1dZW1xdYGJlZmdoaWprbG1vcHFyc3R1dnd4eXp7fH1+gAGCAYUBhgGHAYkBiwGMAY0BjgGPAZABkQGUAZUBlgGXAZgBmQGaAZsBnAGdAZ4BnwGgAaEBogGjAaQBpQGmAacBqAGpAaoBqwGsAa0BrgGvAbABsQGyAbMBtAG1AbYBtwG4AbkBugG7AbwBvQG+Ab8BwAHBAcIBwwHEAcUBxgHHAcgByQHKAcsBzAHNAc4BzwHQAdEB0gHTAdQB1QHWAdcB2AHZAdoB2wHcAd0B3gHgAeEB4gHjAeQB5QHmAecB6AHpAeoB6wHsAe0B7gHvAfAB8QHyAfMBmQKkArAC/gL+AgsgASIEIAJHDfMBQd0BIRAM/wMLIAEiECACRw3dAUHDASEQDP4DCyABIgEgAkcNkAFB9wAhEAz9AwsgASIBIAJHDYYBQe8AIRAM/AMLIAEiASACRw1/QeoAIRAM+wMLIAEiASACRw17QegAIRAM+gMLIAEiASACRw14QeYAIRAM+QMLIAEiASACRw0aQRghEAz4AwsgASIBIAJHDRRBEiEQDPcDCyABIgEgAkcNWUHFACEQDPYDCyABIgEgAkcNSkE/IRAM9QMLIAEiASACRw1IQTwhEAz0AwsgASIBIAJHDUFBMSEQDPMDCyAALQAuQQFGDesDDIcCCyAAIAEiASACEMCAgIAAQQFHDeYBIABCADcDIAznAQsgACABIgEgAhC0gICAACIQDecBIAEhAQz1AgsCQCABIgEgAkcNAEEGIRAM8AMLIAAgAUEBaiIBIAIQu4CAgAAiEA3oASABIQEMMQsgAEIANwMgQRIhEAzVAwsgASIQIAJHDStBHSEQDO0DCwJAIAEiASACRg0AIAFBAWohAUEQIRAM1AMLQQchEAzsAwsgAEIAIAApAyAiESACIAEiEGutIhJ9IhMgEyARVhs3AyAgESASViIURQ3lAUEIIRAM6wMLAkAgASIBIAJGDQAgAEGJgICAADYCCCAAIAE2AgQgASEBQRQhEAzSAwtBCSEQDOoDCyABIQEgACkDIFAN5AEgASEBDPICCwJAIAEiASACRw0AQQshEAzpAwsgACABQQFqIgEgAhC2gICAACIQDeUBIAEhAQzyAgsgACABIgEgAhC4gICAACIQDeUBIAEhAQzyAgsgACABIgEgAhC4gICAACIQDeYBIAEhAQwNCyAAIAEiASACELqAgIAAIhAN5wEgASEBDPACCwJAIAEiASACRw0AQQ8hEAzlAwsgAS0AACIQQTtGDQggEEENRw3oASABQQFqIQEM7wILIAAgASIBIAIQuoCAgAAiEA3oASABIQEM8gILA0ACQCABLQAAQfC1gIAAai0AACIQQQFGDQAgEEECRw3rASAAKAIEIRAgAEEANgIEIAAgECABQQFqIgEQuYCAgAAiEA3qASABIQEM9AILIAFBAWoiASACRw0AC0ESIRAM4gMLIAAgASIBIAIQuoCAgAAiEA3pASABIQEMCgsgASIBIAJHDQZBGyEQDOADCwJAIAEiASACRw0AQRYhEAzgAwsgAEGKgICAADYCCCAAIAE2AgQgACABIAIQuICAgAAiEA3qASABIQFBICEQDMYDCwJAIAEiASACRg0AA0ACQCABLQAAQfC3gIAAai0AACIQQQJGDQACQCAQQX9qDgTlAewBAOsB7AELIAFBAWohAUEIIRAMyAMLIAFBAWoiASACRw0AC0EVIRAM3wMLQRUhEAzeAwsDQAJAIAEtAABB8LmAgABqLQAAIhBBAkYNACAQQX9qDgTeAewB4AHrAewBCyABQQFqIgEgAkcNAAtBGCEQDN0DCwJAIAEiASACRg0AIABBi4CAgAA2AgggACABNgIEIAEhAUEHIRAMxAMLQRkhEAzcAwsgAUEBaiEBDAILAkAgASIUIAJHDQBBGiEQDNsDCyAUIQECQCAULQAAQXNqDhTdAu4C7gLuAu4C7gLuAu4C7gLuAu4C7gLuAu4C7gLuAu4C7gLuAgDuAgtBACEQIABBADYCHCAAQa+LgIAANgIQIABBAjYCDCAAIBRBAWo2AhQM2gMLAkAgAS0AACIQQTtGDQAgEEENRw3oASABQQFqIQEM5QILIAFBAWohAQtBIiEQDL8DCwJAIAEiECACRw0AQRwhEAzYAwtCACERIBAhASAQLQAAQVBqDjfnAeYBAQIDBAUGBwgAAAAAAAAACQoLDA0OAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPEBESExQAC0EeIRAMvQMLQgIhEQzlAQtCAyERDOQBC0IEIREM4wELQgUhEQziAQtCBiERDOEBC0IHIREM4AELQgghEQzfAQtCCSERDN4BC0IKIREM3QELQgshEQzcAQtCDCERDNsBC0INIREM2gELQg4hEQzZAQtCDyERDNgBC0IKIREM1wELQgshEQzWAQtCDCERDNUBC0INIREM1AELQg4hEQzTAQtCDyERDNIBC0IAIRECQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAIBAtAABBUGoON+UB5AEAAQIDBAUGB+YB5gHmAeYB5gHmAeYBCAkKCwwN5gHmAeYB5gHmAeYB5gHmAeYB5gHmAeYB5gHmAeYB5gHmAeYB5gHmAeYB5gHmAeYB5gHmAQ4PEBESE+YBC0ICIREM5AELQgMhEQzjAQtCBCERDOIBC0IFIREM4QELQgYhEQzgAQtCByERDN8BC0IIIREM3gELQgkhEQzdAQtCCiERDNwBC0ILIREM2wELQgwhEQzaAQtCDSERDNkBC0IOIREM2AELQg8hEQzXAQtCCiERDNYBC0ILIREM1QELQgwhEQzUAQtCDSERDNMBC0IOIREM0gELQg8hEQzRAQsgAEIAIAApAyAiESACIAEiEGutIhJ9IhMgEyARVhs3AyAgESASViIURQ3SAUEfIRAMwAMLAkAgASIBIAJGDQAgAEGJgICAADYCCCAAIAE2AgQgASEBQSQhEAynAwtBICEQDL8DCyAAIAEiECACEL6AgIAAQX9qDgW2AQDFAgHRAdIBC0ERIRAMpAMLIABBAToALyAQIQEMuwMLIAEiASACRw3SAUEkIRAMuwMLIAEiDSACRw0eQcYAIRAMugMLIAAgASIBIAIQsoCAgAAiEA3UASABIQEMtQELIAEiECACRw0mQdAAIRAMuAMLAkAgASIBIAJHDQBBKCEQDLgDCyAAQQA2AgQgAEGMgICAADYCCCAAIAEgARCxgICAACIQDdMBIAEhAQzYAQsCQCABIhAgAkcNAEEpIRAMtwMLIBAtAAAiAUEgRg0UIAFBCUcN0wEgEEEBaiEBDBULAkAgASIBIAJGDQAgAUEBaiEBDBcLQSohEAy1AwsCQCABIhAgAkcNAEErIRAMtQMLAkAgEC0AACIBQQlGDQAgAUEgRw3VAQsgAC0ALEEIRg3TASAQIQEMkQMLAkAgASIBIAJHDQBBLCEQDLQDCyABLQAAQQpHDdUBIAFBAWohAQzJAgsgASIOIAJHDdUBQS8hEAyyAwsDQAJAIAEtAAAiEEEgRg0AAkAgEEF2ag4EANwB3AEA2gELIAEhAQzgAQsgAUEBaiIBIAJHDQALQTEhEAyxAwtBMiEQIAEiFCACRg2wAyACIBRrIAAoAgAiAWohFSAUIAFrQQNqIRYCQANAIBQtAAAiF0EgciAXIBdBv39qQf8BcUEaSRtB/wFxIAFB8LuAgABqLQAARw0BAkAgAUEDRw0AQQYhAQyWAwsgAUEBaiEBIBRBAWoiFCACRw0ACyAAIBU2AgAMsQMLIABBADYCACAUIQEM2QELQTMhECABIhQgAkYNrwMgAiAUayAAKAIAIgFqIRUgFCABa0EIaiEWAkADQCAULQAAIhdBIHIgFyAXQb9/akH/AXFBGkkbQf8BcSABQfS7gIAAai0AAEcNAQJAIAFBCEcNAEEFIQEMlQMLIAFBAWohASAUQQFqIhQgAkcNAAsgACAVNgIADLADCyAAQQA2AgAgFCEBDNgBC0E0IRAgASIUIAJGDa4DIAIgFGsgACgCACIBaiEVIBQgAWtBBWohFgJAA0AgFC0AACIXQSByIBcgF0G/f2pB/wFxQRpJG0H/AXEgAUHQwoCAAGotAABHDQECQCABQQVHDQBBByEBDJQDCyABQQFqIQEgFEEBaiIUIAJHDQALIAAgFTYCAAyvAwsgAEEANgIAIBQhAQzXAQsCQCABIgEgAkYNAANAAkAgAS0AAEGAvoCAAGotAAAiEEEBRg0AIBBBAkYNCiABIQEM3QELIAFBAWoiASACRw0AC0EwIRAMrgMLQTAhEAytAwsCQCABIgEgAkYNAANAAkAgAS0AACIQQSBGDQAgEEF2ag4E2QHaAdoB2QHaAQsgAUEBaiIBIAJHDQALQTghEAytAwtBOCEQDKwDCwNAAkAgAS0AACIQQSBGDQAgEEEJRw0DCyABQQFqIgEgAkcNAAtBPCEQDKsDCwNAAkAgAS0AACIQQSBGDQACQAJAIBBBdmoOBNoBAQHaAQALIBBBLEYN2wELIAEhAQwECyABQQFqIgEgAkcNAAtBPyEQDKoDCyABIQEM2wELQcAAIRAgASIUIAJGDagDIAIgFGsgACgCACIBaiEWIBQgAWtBBmohFwJAA0AgFC0AAEEgciABQYDAgIAAai0AAEcNASABQQZGDY4DIAFBAWohASAUQQFqIhQgAkcNAAsgACAWNgIADKkDCyAAQQA2AgAgFCEBC0E2IRAMjgMLAkAgASIPIAJHDQBBwQAhEAynAwsgAEGMgICAADYCCCAAIA82AgQgDyEBIAAtACxBf2oOBM0B1QHXAdkBhwMLIAFBAWohAQzMAQsCQCABIgEgAkYNAANAAkAgAS0AACIQQSByIBAgEEG/f2pB/wFxQRpJG0H/AXEiEEEJRg0AIBBBIEYNAAJAAkACQAJAIBBBnX9qDhMAAwMDAwMDAwEDAwMDAwMDAwMCAwsgAUEBaiEBQTEhEAyRAwsgAUEBaiEBQTIhEAyQAwsgAUEBaiEBQTMhEAyPAwsgASEBDNABCyABQQFqIgEgAkcNAAtBNSEQDKUDC0E1IRAMpAMLAkAgASIBIAJGDQADQAJAIAEtAABBgLyAgABqLQAAQQFGDQAgASEBDNMBCyABQQFqIgEgAkcNAAtBPSEQDKQDC0E9IRAMowMLIAAgASIBIAIQsICAgAAiEA3WASABIQEMAQsgEEEBaiEBC0E8IRAMhwMLAkAgASIBIAJHDQBBwgAhEAygAwsCQANAAkAgAS0AAEF3ag4YAAL+Av4ChAP+Av4C/gL+Av4C/gL+Av4C/gL+Av4C/gL+Av4C/gL+Av4C/gIA/gILIAFBAWoiASACRw0AC0HCACEQDKADCyABQQFqIQEgAC0ALUEBcUUNvQEgASEBC0EsIRAMhQMLIAEiASACRw3TAUHEACEQDJ0DCwNAAkAgAS0AAEGQwICAAGotAABBAUYNACABIQEMtwILIAFBAWoiASACRw0AC0HFACEQDJwDCyANLQAAIhBBIEYNswEgEEE6Rw2BAyAAKAIEIQEgAEEANgIEIAAgASANEK+AgIAAIgEN0AEgDUEBaiEBDLMCC0HHACEQIAEiDSACRg2aAyACIA1rIAAoAgAiAWohFiANIAFrQQVqIRcDQCANLQAAIhRBIHIgFCAUQb9/akH/AXFBGkkbQf8BcSABQZDCgIAAai0AAEcNgAMgAUEFRg30AiABQQFqIQEgDUEBaiINIAJHDQALIAAgFjYCAAyaAwtByAAhECABIg0gAkYNmQMgAiANayAAKAIAIgFqIRYgDSABa0EJaiEXA0AgDS0AACIUQSByIBQgFEG/f2pB/wFxQRpJG0H/AXEgAUGWwoCAAGotAABHDf8CAkAgAUEJRw0AQQIhAQz1AgsgAUEBaiEBIA1BAWoiDSACRw0ACyAAIBY2AgAMmQMLAkAgASINIAJHDQBByQAhEAyZAwsCQAJAIA0tAAAiAUEgciABIAFBv39qQf8BcUEaSRtB/wFxQZJ/ag4HAIADgAOAA4ADgAMBgAMLIA1BAWohAUE+IRAMgAMLIA1BAWohAUE/IRAM/wILQcoAIRAgASINIAJGDZcDIAIgDWsgACgCACIBaiEWIA0gAWtBAWohFwNAIA0tAAAiFEEgciAUIBRBv39qQf8BcUEaSRtB/wFxIAFBoMKAgABqLQAARw39AiABQQFGDfACIAFBAWohASANQQFqIg0gAkcNAAsgACAWNgIADJcDC0HLACEQIAEiDSACRg2WAyACIA1rIAAoAgAiAWohFiANIAFrQQ5qIRcDQCANLQAAIhRBIHIgFCAUQb9/akH/AXFBGkkbQf8BcSABQaLCgIAAai0AAEcN/AIgAUEORg3wAiABQQFqIQEgDUEBaiINIAJHDQALIAAgFjYCAAyWAwtBzAAhECABIg0gAkYNlQMgAiANayAAKAIAIgFqIRYgDSABa0EPaiEXA0AgDS0AACIUQSByIBQgFEG/f2pB/wFxQRpJG0H/AXEgAUHAwoCAAGotAABHDfsCAkAgAUEPRw0AQQMhAQzxAgsgAUEBaiEBIA1BAWoiDSACRw0ACyAAIBY2AgAMlQMLQc0AIRAgASINIAJGDZQDIAIgDWsgACgCACIBaiEWIA0gAWtBBWohFwNAIA0tAAAiFEEgciAUIBRBv39qQf8BcUEaSRtB/wFxIAFB0MKAgABqLQAARw36AgJAIAFBBUcNAEEEIQEM8AILIAFBAWohASANQQFqIg0gAkcNAAsgACAWNgIADJQDCwJAIAEiDSACRw0AQc4AIRAMlAMLAkACQAJAAkAgDS0AACIBQSByIAEgAUG/f2pB/wFxQRpJG0H/AXFBnX9qDhMA/QL9Av0C/QL9Av0C/QL9Av0C/QL9Av0CAf0C/QL9AgID/QILIA1BAWohAUHBACEQDP0CCyANQQFqIQFBwgAhEAz8AgsgDUEBaiEBQcMAIRAM+wILIA1BAWohAUHEACEQDPoCCwJAIAEiASACRg0AIABBjYCAgAA2AgggACABNgIEIAEhAUHFACEQDPoCC0HPACEQDJIDCyAQIQECQAJAIBAtAABBdmoOBAGoAqgCAKgCCyAQQQFqIQELQSchEAz4AgsCQCABIgEgAkcNAEHRACEQDJEDCwJAIAEtAABBIEYNACABIQEMjQELIAFBAWohASAALQAtQQFxRQ3HASABIQEMjAELIAEiFyACRw3IAUHSACEQDI8DC0HTACEQIAEiFCACRg2OAyACIBRrIAAoAgAiAWohFiAUIAFrQQFqIRcDQCAULQAAIAFB1sKAgABqLQAARw3MASABQQFGDccBIAFBAWohASAUQQFqIhQgAkcNAAsgACAWNgIADI4DCwJAIAEiASACRw0AQdUAIRAMjgMLIAEtAABBCkcNzAEgAUEBaiEBDMcBCwJAIAEiASACRw0AQdYAIRAMjQMLAkACQCABLQAAQXZqDgQAzQHNAQHNAQsgAUEBaiEBDMcBCyABQQFqIQFBygAhEAzzAgsgACABIgEgAhCugICAACIQDcsBIAEhAUHNACEQDPICCyAALQApQSJGDYUDDKYCCwJAIAEiASACRw0AQdsAIRAMigMLQQAhFEEBIRdBASEWQQAhEAJAAkACQAJAAkACQAJAAkACQCABLQAAQVBqDgrUAdMBAAECAwQFBgjVAQtBAiEQDAYLQQMhEAwFC0EEIRAMBAtBBSEQDAMLQQYhEAwCC0EHIRAMAQtBCCEQC0EAIRdBACEWQQAhFAzMAQtBCSEQQQEhFEEAIRdBACEWDMsBCwJAIAEiASACRw0AQd0AIRAMiQMLIAEtAABBLkcNzAEgAUEBaiEBDKYCCyABIgEgAkcNzAFB3wAhEAyHAwsCQCABIgEgAkYNACAAQY6AgIAANgIIIAAgATYCBCABIQFB0AAhEAzuAgtB4AAhEAyGAwtB4QAhECABIgEgAkYNhQMgAiABayAAKAIAIhRqIRYgASAUa0EDaiEXA0AgAS0AACAUQeLCgIAAai0AAEcNzQEgFEEDRg3MASAUQQFqIRQgAUEBaiIBIAJHDQALIAAgFjYCAAyFAwtB4gAhECABIgEgAkYNhAMgAiABayAAKAIAIhRqIRYgASAUa0ECaiEXA0AgAS0AACAUQebCgIAAai0AAEcNzAEgFEECRg3OASAUQQFqIRQgAUEBaiIBIAJHDQALIAAgFjYCAAyEAwtB4wAhECABIgEgAkYNgwMgAiABayAAKAIAIhRqIRYgASAUa0EDaiEXA0AgAS0AACAUQenCgIAAai0AAEcNywEgFEEDRg3OASAUQQFqIRQgAUEBaiIBIAJHDQALIAAgFjYCAAyDAwsCQCABIgEgAkcNAEHlACEQDIMDCyAAIAFBAWoiASACEKiAgIAAIhANzQEgASEBQdYAIRAM6QILAkAgASIBIAJGDQADQAJAIAEtAAAiEEEgRg0AAkACQAJAIBBBuH9qDgsAAc8BzwHPAc8BzwHPAc8BzwECzwELIAFBAWohAUHSACEQDO0CCyABQQFqIQFB0wAhEAzsAgsgAUEBaiEBQdQAIRAM6wILIAFBAWoiASACRw0AC0HkACEQDIIDC0HkACEQDIEDCwNAAkAgAS0AAEHwwoCAAGotAAAiEEEBRg0AIBBBfmoOA88B0AHRAdIBCyABQQFqIgEgAkcNAAtB5gAhEAyAAwsCQCABIgEgAkYNACABQQFqIQEMAwtB5wAhEAz/AgsDQAJAIAEtAABB8MSAgABqLQAAIhBBAUYNAAJAIBBBfmoOBNIB0wHUAQDVAQsgASEBQdcAIRAM5wILIAFBAWoiASACRw0AC0HoACEQDP4CCwJAIAEiASACRw0AQekAIRAM/gILAkAgAS0AACIQQXZqDhq6AdUB1QG8AdUB1QHVAdUB1QHVAdUB1QHVAdUB1QHVAdUB1QHVAdUB1QHVAcoB1QHVAQDTAQsgAUEBaiEBC0EGIRAM4wILA0ACQCABLQAAQfDGgIAAai0AAEEBRg0AIAEhAQyeAgsgAUEBaiIBIAJHDQALQeoAIRAM+wILAkAgASIBIAJGDQAgAUEBaiEBDAMLQesAIRAM+gILAkAgASIBIAJHDQBB7AAhEAz6AgsgAUEBaiEBDAELAkAgASIBIAJHDQBB7QAhEAz5AgsgAUEBaiEBC0EEIRAM3gILAkAgASIUIAJHDQBB7gAhEAz3AgsgFCEBAkACQAJAIBQtAABB8MiAgABqLQAAQX9qDgfUAdUB1gEAnAIBAtcBCyAUQQFqIQEMCgsgFEEBaiEBDM0BC0EAIRAgAEEANgIcIABBm5KAgAA2AhAgAEEHNgIMIAAgFEEBajYCFAz2AgsCQANAAkAgAS0AAEHwyICAAGotAAAiEEEERg0AAkACQCAQQX9qDgfSAdMB1AHZAQAEAdkBCyABIQFB2gAhEAzgAgsgAUEBaiEBQdwAIRAM3wILIAFBAWoiASACRw0AC0HvACEQDPYCCyABQQFqIQEMywELAkAgASIUIAJHDQBB8AAhEAz1AgsgFC0AAEEvRw3UASAUQQFqIQEMBgsCQCABIhQgAkcNAEHxACEQDPQCCwJAIBQtAAAiAUEvRw0AIBRBAWohAUHdACEQDNsCCyABQXZqIgRBFksN0wFBASAEdEGJgIACcUUN0wEMygILAkAgASIBIAJGDQAgAUEBaiEBQd4AIRAM2gILQfIAIRAM8gILAkAgASIUIAJHDQBB9AAhEAzyAgsgFCEBAkAgFC0AAEHwzICAAGotAABBf2oOA8kClAIA1AELQeEAIRAM2AILAkAgASIUIAJGDQADQAJAIBQtAABB8MqAgABqLQAAIgFBA0YNAAJAIAFBf2oOAssCANUBCyAUIQFB3wAhEAzaAgsgFEEBaiIUIAJHDQALQfMAIRAM8QILQfMAIRAM8AILAkAgASIBIAJGDQAgAEGPgICAADYCCCAAIAE2AgQgASEBQeAAIRAM1wILQfUAIRAM7wILAkAgASIBIAJHDQBB9gAhEAzvAgsgAEGPgICAADYCCCAAIAE2AgQgASEBC0EDIRAM1AILA0AgAS0AAEEgRw3DAiABQQFqIgEgAkcNAAtB9wAhEAzsAgsCQCABIgEgAkcNAEH4ACEQDOwCCyABLQAAQSBHDc4BIAFBAWohAQzvAQsgACABIgEgAhCsgICAACIQDc4BIAEhAQyOAgsCQCABIgQgAkcNAEH6ACEQDOoCCyAELQAAQcwARw3RASAEQQFqIQFBEyEQDM8BCwJAIAEiBCACRw0AQfsAIRAM6QILIAIgBGsgACgCACIBaiEUIAQgAWtBBWohEANAIAQtAAAgAUHwzoCAAGotAABHDdABIAFBBUYNzgEgAUEBaiEBIARBAWoiBCACRw0ACyAAIBQ2AgBB+wAhEAzoAgsCQCABIgQgAkcNAEH8ACEQDOgCCwJAAkAgBC0AAEG9f2oODADRAdEB0QHRAdEB0QHRAdEB0QHRAQHRAQsgBEEBaiEBQeYAIRAMzwILIARBAWohAUHnACEQDM4CCwJAIAEiBCACRw0AQf0AIRAM5wILIAIgBGsgACgCACIBaiEUIAQgAWtBAmohEAJAA0AgBC0AACABQe3PgIAAai0AAEcNzwEgAUECRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQf0AIRAM5wILIABBADYCACAQQQFqIQFBECEQDMwBCwJAIAEiBCACRw0AQf4AIRAM5gILIAIgBGsgACgCACIBaiEUIAQgAWtBBWohEAJAA0AgBC0AACABQfbOgIAAai0AAEcNzgEgAUEFRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQf4AIRAM5gILIABBADYCACAQQQFqIQFBFiEQDMsBCwJAIAEiBCACRw0AQf8AIRAM5QILIAIgBGsgACgCACIBaiEUIAQgAWtBA2ohEAJAA0AgBC0AACABQfzOgIAAai0AAEcNzQEgAUEDRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQf8AIRAM5QILIABBADYCACAQQQFqIQFBBSEQDMoBCwJAIAEiBCACRw0AQYABIRAM5AILIAQtAABB2QBHDcsBIARBAWohAUEIIRAMyQELAkAgASIEIAJHDQBBgQEhEAzjAgsCQAJAIAQtAABBsn9qDgMAzAEBzAELIARBAWohAUHrACEQDMoCCyAEQQFqIQFB7AAhEAzJAgsCQCABIgQgAkcNAEGCASEQDOICCwJAAkAgBC0AAEG4f2oOCADLAcsBywHLAcsBywEBywELIARBAWohAUHqACEQDMkCCyAEQQFqIQFB7QAhEAzIAgsCQCABIgQgAkcNAEGDASEQDOECCyACIARrIAAoAgAiAWohECAEIAFrQQJqIRQCQANAIAQtAAAgAUGAz4CAAGotAABHDckBIAFBAkYNASABQQFqIQEgBEEBaiIEIAJHDQALIAAgEDYCAEGDASEQDOECC0EAIRAgAEEANgIAIBRBAWohAQzGAQsCQCABIgQgAkcNAEGEASEQDOACCyACIARrIAAoAgAiAWohFCAEIAFrQQRqIRACQANAIAQtAAAgAUGDz4CAAGotAABHDcgBIAFBBEYNASABQQFqIQEgBEEBaiIEIAJHDQALIAAgFDYCAEGEASEQDOACCyAAQQA2AgAgEEEBaiEBQSMhEAzFAQsCQCABIgQgAkcNAEGFASEQDN8CCwJAAkAgBC0AAEG0f2oOCADIAcgByAHIAcgByAEByAELIARBAWohAUHvACEQDMYCCyAEQQFqIQFB8AAhEAzFAgsCQCABIgQgAkcNAEGGASEQDN4CCyAELQAAQcUARw3FASAEQQFqIQEMgwILAkAgASIEIAJHDQBBhwEhEAzdAgsgAiAEayAAKAIAIgFqIRQgBCABa0EDaiEQAkADQCAELQAAIAFBiM+AgABqLQAARw3FASABQQNGDQEgAUEBaiEBIARBAWoiBCACRw0ACyAAIBQ2AgBBhwEhEAzdAgsgAEEANgIAIBBBAWohAUEtIRAMwgELAkAgASIEIAJHDQBBiAEhEAzcAgsgAiAEayAAKAIAIgFqIRQgBCABa0EIaiEQAkADQCAELQAAIAFB0M+AgABqLQAARw3EASABQQhGDQEgAUEBaiEBIARBAWoiBCACRw0ACyAAIBQ2AgBBiAEhEAzcAgsgAEEANgIAIBBBAWohAUEpIRAMwQELAkAgASIBIAJHDQBBiQEhEAzbAgtBASEQIAEtAABB3wBHDcABIAFBAWohAQyBAgsCQCABIgQgAkcNAEGKASEQDNoCCyACIARrIAAoAgAiAWohFCAEIAFrQQFqIRADQCAELQAAIAFBjM+AgABqLQAARw3BASABQQFGDa8CIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQYoBIRAM2QILAkAgASIEIAJHDQBBiwEhEAzZAgsgAiAEayAAKAIAIgFqIRQgBCABa0ECaiEQAkADQCAELQAAIAFBjs+AgABqLQAARw3BASABQQJGDQEgAUEBaiEBIARBAWoiBCACRw0ACyAAIBQ2AgBBiwEhEAzZAgsgAEEANgIAIBBBAWohAUECIRAMvgELAkAgASIEIAJHDQBBjAEhEAzYAgsgAiAEayAAKAIAIgFqIRQgBCABa0EBaiEQAkADQCAELQAAIAFB8M+AgABqLQAARw3AASABQQFGDQEgAUEBaiEBIARBAWoiBCACRw0ACyAAIBQ2AgBBjAEhEAzYAgsgAEEANgIAIBBBAWohAUEfIRAMvQELAkAgASIEIAJHDQBBjQEhEAzXAgsgAiAEayAAKAIAIgFqIRQgBCABa0EBaiEQAkADQCAELQAAIAFB8s+AgABqLQAARw2/ASABQQFGDQEgAUEBaiEBIARBAWoiBCACRw0ACyAAIBQ2AgBBjQEhEAzXAgsgAEEANgIAIBBBAWohAUEJIRAMvAELAkAgASIEIAJHDQBBjgEhEAzWAgsCQAJAIAQtAABBt39qDgcAvwG/Ab8BvwG/AQG/AQsgBEEBaiEBQfgAIRAMvQILIARBAWohAUH5ACEQDLwCCwJAIAEiBCACRw0AQY8BIRAM1QILIAIgBGsgACgCACIBaiEUIAQgAWtBBWohEAJAA0AgBC0AACABQZHPgIAAai0AAEcNvQEgAUEFRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQY8BIRAM1QILIABBADYCACAQQQFqIQFBGCEQDLoBCwJAIAEiBCACRw0AQZABIRAM1AILIAIgBGsgACgCACIBaiEUIAQgAWtBAmohEAJAA0AgBC0AACABQZfPgIAAai0AAEcNvAEgAUECRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQZABIRAM1AILIABBADYCACAQQQFqIQFBFyEQDLkBCwJAIAEiBCACRw0AQZEBIRAM0wILIAIgBGsgACgCACIBaiEUIAQgAWtBBmohEAJAA0AgBC0AACABQZrPgIAAai0AAEcNuwEgAUEGRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQZEBIRAM0wILIABBADYCACAQQQFqIQFBFSEQDLgBCwJAIAEiBCACRw0AQZIBIRAM0gILIAIgBGsgACgCACIBaiEUIAQgAWtBBWohEAJAA0AgBC0AACABQaHPgIAAai0AAEcNugEgAUEFRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQZIBIRAM0gILIABBADYCACAQQQFqIQFBHiEQDLcBCwJAIAEiBCACRw0AQZMBIRAM0QILIAQtAABBzABHDbgBIARBAWohAUEKIRAMtgELAkAgBCACRw0AQZQBIRAM0AILAkACQCAELQAAQb9/ag4PALkBuQG5AbkBuQG5AbkBuQG5AbkBuQG5AbkBAbkBCyAEQQFqIQFB/gAhEAy3AgsgBEEBaiEBQf8AIRAMtgILAkAgBCACRw0AQZUBIRAMzwILAkACQCAELQAAQb9/ag4DALgBAbgBCyAEQQFqIQFB/QAhEAy2AgsgBEEBaiEEQYABIRAMtQILAkAgBCACRw0AQZYBIRAMzgILIAIgBGsgACgCACIBaiEUIAQgAWtBAWohEAJAA0AgBC0AACABQafPgIAAai0AAEcNtgEgAUEBRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQZYBIRAMzgILIABBADYCACAQQQFqIQFBCyEQDLMBCwJAIAQgAkcNAEGXASEQDM0CCwJAAkACQAJAIAQtAABBU2oOIwC4AbgBuAG4AbgBuAG4AbgBuAG4AbgBuAG4AbgBuAG4AbgBuAG4AbgBuAG4AbgBAbgBuAG4AbgBuAECuAG4AbgBA7gBCyAEQQFqIQFB+wAhEAy2AgsgBEEBaiEBQfwAIRAMtQILIARBAWohBEGBASEQDLQCCyAEQQFqIQRBggEhEAyzAgsCQCAEIAJHDQBBmAEhEAzMAgsgAiAEayAAKAIAIgFqIRQgBCABa0EEaiEQAkADQCAELQAAIAFBqc+AgABqLQAARw20ASABQQRGDQEgAUEBaiEBIARBAWoiBCACRw0ACyAAIBQ2AgBBmAEhEAzMAgsgAEEANgIAIBBBAWohAUEZIRAMsQELAkAgBCACRw0AQZkBIRAMywILIAIgBGsgACgCACIBaiEUIAQgAWtBBWohEAJAA0AgBC0AACABQa7PgIAAai0AAEcNswEgAUEFRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQZkBIRAMywILIABBADYCACAQQQFqIQFBBiEQDLABCwJAIAQgAkcNAEGaASEQDMoCCyACIARrIAAoAgAiAWohFCAEIAFrQQFqIRACQANAIAQtAAAgAUG0z4CAAGotAABHDbIBIAFBAUYNASABQQFqIQEgBEEBaiIEIAJHDQALIAAgFDYCAEGaASEQDMoCCyAAQQA2AgAgEEEBaiEBQRwhEAyvAQsCQCAEIAJHDQBBmwEhEAzJAgsgAiAEayAAKAIAIgFqIRQgBCABa0EBaiEQAkADQCAELQAAIAFBts+AgABqLQAARw2xASABQQFGDQEgAUEBaiEBIARBAWoiBCACRw0ACyAAIBQ2AgBBmwEhEAzJAgsgAEEANgIAIBBBAWohAUEnIRAMrgELAkAgBCACRw0AQZwBIRAMyAILAkACQCAELQAAQax/ag4CAAGxAQsgBEEBaiEEQYYBIRAMrwILIARBAWohBEGHASEQDK4CCwJAIAQgAkcNAEGdASEQDMcCCyACIARrIAAoAgAiAWohFCAEIAFrQQFqIRACQANAIAQtAAAgAUG4z4CAAGotAABHDa8BIAFBAUYNASABQQFqIQEgBEEBaiIEIAJHDQALIAAgFDYCAEGdASEQDMcCCyAAQQA2AgAgEEEBaiEBQSYhEAysAQsCQCAEIAJHDQBBngEhEAzGAgsgAiAEayAAKAIAIgFqIRQgBCABa0EBaiEQAkADQCAELQAAIAFBus+AgABqLQAARw2uASABQQFGDQEgAUEBaiEBIARBAWoiBCACRw0ACyAAIBQ2AgBBngEhEAzGAgsgAEEANgIAIBBBAWohAUEDIRAMqwELAkAgBCACRw0AQZ8BIRAMxQILIAIgBGsgACgCACIBaiEUIAQgAWtBAmohEAJAA0AgBC0AACABQe3PgIAAai0AAEcNrQEgAUECRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQZ8BIRAMxQILIABBADYCACAQQQFqIQFBDCEQDKoBCwJAIAQgAkcNAEGgASEQDMQCCyACIARrIAAoAgAiAWohFCAEIAFrQQNqIRACQANAIAQtAAAgAUG8z4CAAGotAABHDawBIAFBA0YNASABQQFqIQEgBEEBaiIEIAJHDQALIAAgFDYCAEGgASEQDMQCCyAAQQA2AgAgEEEBaiEBQQ0hEAypAQsCQCAEIAJHDQBBoQEhEAzDAgsCQAJAIAQtAABBun9qDgsArAGsAawBrAGsAawBrAGsAawBAawBCyAEQQFqIQRBiwEhEAyqAgsgBEEBaiEEQYwBIRAMqQILAkAgBCACRw0AQaIBIRAMwgILIAQtAABB0ABHDakBIARBAWohBAzpAQsCQCAEIAJHDQBBowEhEAzBAgsCQAJAIAQtAABBt39qDgcBqgGqAaoBqgGqAQCqAQsgBEEBaiEEQY4BIRAMqAILIARBAWohAUEiIRAMpgELAkAgBCACRw0AQaQBIRAMwAILIAIgBGsgACgCACIBaiEUIAQgAWtBAWohEAJAA0AgBC0AACABQcDPgIAAai0AAEcNqAEgAUEBRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQaQBIRAMwAILIABBADYCACAQQQFqIQFBHSEQDKUBCwJAIAQgAkcNAEGlASEQDL8CCwJAAkAgBC0AAEGuf2oOAwCoAQGoAQsgBEEBaiEEQZABIRAMpgILIARBAWohAUEEIRAMpAELAkAgBCACRw0AQaYBIRAMvgILAkACQAJAAkACQCAELQAAQb9/ag4VAKoBqgGqAaoBqgGqAaoBqgGqAaoBAaoBqgECqgGqAQOqAaoBBKoBCyAEQQFqIQRBiAEhEAyoAgsgBEEBaiEEQYkBIRAMpwILIARBAWohBEGKASEQDKYCCyAEQQFqIQRBjwEhEAylAgsgBEEBaiEEQZEBIRAMpAILAkAgBCACRw0AQacBIRAMvQILIAIgBGsgACgCACIBaiEUIAQgAWtBAmohEAJAA0AgBC0AACABQe3PgIAAai0AAEcNpQEgAUECRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQacBIRAMvQILIABBADYCACAQQQFqIQFBESEQDKIBCwJAIAQgAkcNAEGoASEQDLwCCyACIARrIAAoAgAiAWohFCAEIAFrQQJqIRACQANAIAQtAAAgAUHCz4CAAGotAABHDaQBIAFBAkYNASABQQFqIQEgBEEBaiIEIAJHDQALIAAgFDYCAEGoASEQDLwCCyAAQQA2AgAgEEEBaiEBQSwhEAyhAQsCQCAEIAJHDQBBqQEhEAy7AgsgAiAEayAAKAIAIgFqIRQgBCABa0EEaiEQAkADQCAELQAAIAFBxc+AgABqLQAARw2jASABQQRGDQEgAUEBaiEBIARBAWoiBCACRw0ACyAAIBQ2AgBBqQEhEAy7AgsgAEEANgIAIBBBAWohAUErIRAMoAELAkAgBCACRw0AQaoBIRAMugILIAIgBGsgACgCACIBaiEUIAQgAWtBAmohEAJAA0AgBC0AACABQcrPgIAAai0AAEcNogEgAUECRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQaoBIRAMugILIABBADYCACAQQQFqIQFBFCEQDJ8BCwJAIAQgAkcNAEGrASEQDLkCCwJAAkACQAJAIAQtAABBvn9qDg8AAQKkAaQBpAGkAaQBpAGkAaQBpAGkAaQBA6QBCyAEQQFqIQRBkwEhEAyiAgsgBEEBaiEEQZQBIRAMoQILIARBAWohBEGVASEQDKACCyAEQQFqIQRBlgEhEAyfAgsCQCAEIAJHDQBBrAEhEAy4AgsgBC0AAEHFAEcNnwEgBEEBaiEEDOABCwJAIAQgAkcNAEGtASEQDLcCCyACIARrIAAoAgAiAWohFCAEIAFrQQJqIRACQANAIAQtAAAgAUHNz4CAAGotAABHDZ8BIAFBAkYNASABQQFqIQEgBEEBaiIEIAJHDQALIAAgFDYCAEGtASEQDLcCCyAAQQA2AgAgEEEBaiEBQQ4hEAycAQsCQCAEIAJHDQBBrgEhEAy2AgsgBC0AAEHQAEcNnQEgBEEBaiEBQSUhEAybAQsCQCAEIAJHDQBBrwEhEAy1AgsgAiAEayAAKAIAIgFqIRQgBCABa0EIaiEQAkADQCAELQAAIAFB0M+AgABqLQAARw2dASABQQhGDQEgAUEBaiEBIARBAWoiBCACRw0ACyAAIBQ2AgBBrwEhEAy1AgsgAEEANgIAIBBBAWohAUEqIRAMmgELAkAgBCACRw0AQbABIRAMtAILAkACQCAELQAAQat/ag4LAJ0BnQGdAZ0BnQGdAZ0BnQGdAQGdAQsgBEEBaiEEQZoBIRAMmwILIARBAWohBEGbASEQDJoCCwJAIAQgAkcNAEGxASEQDLMCCwJAAkAgBC0AAEG/f2oOFACcAZwBnAGcAZwBnAGcAZwBnAGcAZwBnAGcAZwBnAGcAZwBnAEBnAELIARBAWohBEGZASEQDJoCCyAEQQFqIQRBnAEhEAyZAgsCQCAEIAJHDQBBsgEhEAyyAgsgAiAEayAAKAIAIgFqIRQgBCABa0EDaiEQAkADQCAELQAAIAFB2c+AgABqLQAARw2aASABQQNGDQEgAUEBaiEBIARBAWoiBCACRw0ACyAAIBQ2AgBBsgEhEAyyAgsgAEEANgIAIBBBAWohAUEhIRAMlwELAkAgBCACRw0AQbMBIRAMsQILIAIgBGsgACgCACIBaiEUIAQgAWtBBmohEAJAA0AgBC0AACABQd3PgIAAai0AAEcNmQEgAUEGRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQbMBIRAMsQILIABBADYCACAQQQFqIQFBGiEQDJYBCwJAIAQgAkcNAEG0ASEQDLACCwJAAkACQCAELQAAQbt/ag4RAJoBmgGaAZoBmgGaAZoBmgGaAQGaAZoBmgGaAZoBApoBCyAEQQFqIQRBnQEhEAyYAgsgBEEBaiEEQZ4BIRAMlwILIARBAWohBEGfASEQDJYCCwJAIAQgAkcNAEG1ASEQDK8CCyACIARrIAAoAgAiAWohFCAEIAFrQQVqIRACQANAIAQtAAAgAUHkz4CAAGotAABHDZcBIAFBBUYNASABQQFqIQEgBEEBaiIEIAJHDQALIAAgFDYCAEG1ASEQDK8CCyAAQQA2AgAgEEEBaiEBQSghEAyUAQsCQCAEIAJHDQBBtgEhEAyuAgsgAiAEayAAKAIAIgFqIRQgBCABa0ECaiEQAkADQCAELQAAIAFB6s+AgABqLQAARw2WASABQQJGDQEgAUEBaiEBIARBAWoiBCACRw0ACyAAIBQ2AgBBtgEhEAyuAgsgAEEANgIAIBBBAWohAUEHIRAMkwELAkAgBCACRw0AQbcBIRAMrQILAkACQCAELQAAQbt/ag4OAJYBlgGWAZYBlgGWAZYBlgGWAZYBlgGWAQGWAQsgBEEBaiEEQaEBIRAMlAILIARBAWohBEGiASEQDJMCCwJAIAQgAkcNAEG4ASEQDKwCCyACIARrIAAoAgAiAWohFCAEIAFrQQJqIRACQANAIAQtAAAgAUHtz4CAAGotAABHDZQBIAFBAkYNASABQQFqIQEgBEEBaiIEIAJHDQALIAAgFDYCAEG4ASEQDKwCCyAAQQA2AgAgEEEBaiEBQRIhEAyRAQsCQCAEIAJHDQBBuQEhEAyrAgsgAiAEayAAKAIAIgFqIRQgBCABa0EBaiEQAkADQCAELQAAIAFB8M+AgABqLQAARw2TASABQQFGDQEgAUEBaiEBIARBAWoiBCACRw0ACyAAIBQ2AgBBuQEhEAyrAgsgAEEANgIAIBBBAWohAUEgIRAMkAELAkAgBCACRw0AQboBIRAMqgILIAIgBGsgACgCACIBaiEUIAQgAWtBAWohEAJAA0AgBC0AACABQfLPgIAAai0AAEcNkgEgAUEBRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQboBIRAMqgILIABBADYCACAQQQFqIQFBDyEQDI8BCwJAIAQgAkcNAEG7ASEQDKkCCwJAAkAgBC0AAEG3f2oOBwCSAZIBkgGSAZIBAZIBCyAEQQFqIQRBpQEhEAyQAgsgBEEBaiEEQaYBIRAMjwILAkAgBCACRw0AQbwBIRAMqAILIAIgBGsgACgCACIBaiEUIAQgAWtBB2ohEAJAA0AgBC0AACABQfTPgIAAai0AAEcNkAEgAUEHRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQbwBIRAMqAILIABBADYCACAQQQFqIQFBGyEQDI0BCwJAIAQgAkcNAEG9ASEQDKcCCwJAAkACQCAELQAAQb5/ag4SAJEBkQGRAZEBkQGRAZEBkQGRAQGRAZEBkQGRAZEBkQECkQELIARBAWohBEGkASEQDI8CCyAEQQFqIQRBpwEhEAyOAgsgBEEBaiEEQagBIRAMjQILAkAgBCACRw0AQb4BIRAMpgILIAQtAABBzgBHDY0BIARBAWohBAzPAQsCQCAEIAJHDQBBvwEhEAylAgsCQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQCAELQAAQb9/ag4VAAECA5wBBAUGnAGcAZwBBwgJCgucAQwNDg+cAQsgBEEBaiEBQegAIRAMmgILIARBAWohAUHpACEQDJkCCyAEQQFqIQFB7gAhEAyYAgsgBEEBaiEBQfIAIRAMlwILIARBAWohAUHzACEQDJYCCyAEQQFqIQFB9gAhEAyVAgsgBEEBaiEBQfcAIRAMlAILIARBAWohAUH6ACEQDJMCCyAEQQFqIQRBgwEhEAySAgsgBEEBaiEEQYQBIRAMkQILIARBAWohBEGFASEQDJACCyAEQQFqIQRBkgEhEAyPAgsgBEEBaiEEQZgBIRAMjgILIARBAWohBEGgASEQDI0CCyAEQQFqIQRBowEhEAyMAgsgBEEBaiEEQaoBIRAMiwILAkAgBCACRg0AIABBkICAgAA2AgggACAENgIEQasBIRAMiwILQcABIRAMowILIAAgBSACEKqAgIAAIgENiwEgBSEBDFwLAkAgBiACRg0AIAZBAWohBQyNAQtBwgEhEAyhAgsDQAJAIBAtAABBdmoOBIwBAACPAQALIBBBAWoiECACRw0AC0HDASEQDKACCwJAIAcgAkYNACAAQZGAgIAANgIIIAAgBzYCBCAHIQFBASEQDIcCC0HEASEQDJ8CCwJAIAcgAkcNAEHFASEQDJ8CCwJAAkAgBy0AAEF2ag4EAc4BzgEAzgELIAdBAWohBgyNAQsgB0EBaiEFDIkBCwJAIAcgAkcNAEHGASEQDJ4CCwJAAkAgBy0AAEF2ag4XAY8BjwEBjwGPAY8BjwGPAY8BjwGPAY8BjwGPAY8BjwGPAY8BjwGPAY8BAI8BCyAHQQFqIQcLQbABIRAMhAILAkAgCCACRw0AQcgBIRAMnQILIAgtAABBIEcNjQEgAEEAOwEyIAhBAWohAUGzASEQDIMCCyABIRcCQANAIBciByACRg0BIActAABBUGpB/wFxIhBBCk8NzAECQCAALwEyIhRBmTNLDQAgACAUQQpsIhQ7ATIgEEH//wNzIBRB/v8DcUkNACAHQQFqIRcgACAUIBBqIhA7ATIgEEH//wNxQegHSQ0BCwtBACEQIABBADYCHCAAQcGJgIAANgIQIABBDTYCDCAAIAdBAWo2AhQMnAILQccBIRAMmwILIAAgCCACEK6AgIAAIhBFDcoBIBBBFUcNjAEgAEHIATYCHCAAIAg2AhQgAEHJl4CAADYCECAAQRU2AgxBACEQDJoCCwJAIAkgAkcNAEHMASEQDJoCC0EAIRRBASEXQQEhFkEAIRACQAJAAkACQAJAAkACQAJAAkAgCS0AAEFQag4KlgGVAQABAgMEBQYIlwELQQIhEAwGC0EDIRAMBQtBBCEQDAQLQQUhEAwDC0EGIRAMAgtBByEQDAELQQghEAtBACEXQQAhFkEAIRQMjgELQQkhEEEBIRRBACEXQQAhFgyNAQsCQCAKIAJHDQBBzgEhEAyZAgsgCi0AAEEuRw2OASAKQQFqIQkMygELIAsgAkcNjgFB0AEhEAyXAgsCQCALIAJGDQAgAEGOgICAADYCCCAAIAs2AgRBtwEhEAz+AQtB0QEhEAyWAgsCQCAEIAJHDQBB0gEhEAyWAgsgAiAEayAAKAIAIhBqIRQgBCAQa0EEaiELA0AgBC0AACAQQfzPgIAAai0AAEcNjgEgEEEERg3pASAQQQFqIRAgBEEBaiIEIAJHDQALIAAgFDYCAEHSASEQDJUCCyAAIAwgAhCsgICAACIBDY0BIAwhAQy4AQsCQCAEIAJHDQBB1AEhEAyUAgsgAiAEayAAKAIAIhBqIRQgBCAQa0EBaiEMA0AgBC0AACAQQYHQgIAAai0AAEcNjwEgEEEBRg2OASAQQQFqIRAgBEEBaiIEIAJHDQALIAAgFDYCAEHUASEQDJMCCwJAIAQgAkcNAEHWASEQDJMCCyACIARrIAAoAgAiEGohFCAEIBBrQQJqIQsDQCAELQAAIBBBg9CAgABqLQAARw2OASAQQQJGDZABIBBBAWohECAEQQFqIgQgAkcNAAsgACAUNgIAQdYBIRAMkgILAkAgBCACRw0AQdcBIRAMkgILAkACQCAELQAAQbt/ag4QAI8BjwGPAY8BjwGPAY8BjwGPAY8BjwGPAY8BjwEBjwELIARBAWohBEG7ASEQDPkBCyAEQQFqIQRBvAEhEAz4AQsCQCAEIAJHDQBB2AEhEAyRAgsgBC0AAEHIAEcNjAEgBEEBaiEEDMQBCwJAIAQgAkYNACAAQZCAgIAANgIIIAAgBDYCBEG+ASEQDPcBC0HZASEQDI8CCwJAIAQgAkcNAEHaASEQDI8CCyAELQAAQcgARg3DASAAQQE6ACgMuQELIABBAjoALyAAIAQgAhCmgICAACIQDY0BQcIBIRAM9AELIAAtAChBf2oOArcBuQG4AQsDQAJAIAQtAABBdmoOBACOAY4BAI4BCyAEQQFqIgQgAkcNAAtB3QEhEAyLAgsgAEEAOgAvIAAtAC1BBHFFDYQCCyAAQQA6AC8gAEEBOgA0IAEhAQyMAQsgEEEVRg3aASAAQQA2AhwgACABNgIUIABBp46AgAA2AhAgAEESNgIMQQAhEAyIAgsCQCAAIBAgAhC0gICAACIEDQAgECEBDIECCwJAIARBFUcNACAAQQM2AhwgACAQNgIUIABBsJiAgAA2AhAgAEEVNgIMQQAhEAyIAgsgAEEANgIcIAAgEDYCFCAAQaeOgIAANgIQIABBEjYCDEEAIRAMhwILIBBBFUYN1gEgAEEANgIcIAAgATYCFCAAQdqNgIAANgIQIABBFDYCDEEAIRAMhgILIAAoAgQhFyAAQQA2AgQgECARp2oiFiEBIAAgFyAQIBYgFBsiEBC1gICAACIURQ2NASAAQQc2AhwgACAQNgIUIAAgFDYCDEEAIRAMhQILIAAgAC8BMEGAAXI7ATAgASEBC0EqIRAM6gELIBBBFUYN0QEgAEEANgIcIAAgATYCFCAAQYOMgIAANgIQIABBEzYCDEEAIRAMggILIBBBFUYNzwEgAEEANgIcIAAgATYCFCAAQZqPgIAANgIQIABBIjYCDEEAIRAMgQILIAAoAgQhECAAQQA2AgQCQCAAIBAgARC3gICAACIQDQAgAUEBaiEBDI0BCyAAQQw2AhwgACAQNgIMIAAgAUEBajYCFEEAIRAMgAILIBBBFUYNzAEgAEEANgIcIAAgATYCFCAAQZqPgIAANgIQIABBIjYCDEEAIRAM/wELIAAoAgQhECAAQQA2AgQCQCAAIBAgARC3gICAACIQDQAgAUEBaiEBDIwBCyAAQQ02AhwgACAQNgIMIAAgAUEBajYCFEEAIRAM/gELIBBBFUYNyQEgAEEANgIcIAAgATYCFCAAQcaMgIAANgIQIABBIzYCDEEAIRAM/QELIAAoAgQhECAAQQA2AgQCQCAAIBAgARC5gICAACIQDQAgAUEBaiEBDIsBCyAAQQ42AhwgACAQNgIMIAAgAUEBajYCFEEAIRAM/AELIABBADYCHCAAIAE2AhQgAEHAlYCAADYCECAAQQI2AgxBACEQDPsBCyAQQRVGDcUBIABBADYCHCAAIAE2AhQgAEHGjICAADYCECAAQSM2AgxBACEQDPoBCyAAQRA2AhwgACABNgIUIAAgEDYCDEEAIRAM+QELIAAoAgQhBCAAQQA2AgQCQCAAIAQgARC5gICAACIEDQAgAUEBaiEBDPEBCyAAQRE2AhwgACAENgIMIAAgAUEBajYCFEEAIRAM+AELIBBBFUYNwQEgAEEANgIcIAAgATYCFCAAQcaMgIAANgIQIABBIzYCDEEAIRAM9wELIAAoAgQhECAAQQA2AgQCQCAAIBAgARC5gICAACIQDQAgAUEBaiEBDIgBCyAAQRM2AhwgACAQNgIMIAAgAUEBajYCFEEAIRAM9gELIAAoAgQhBCAAQQA2AgQCQCAAIAQgARC5gICAACIEDQAgAUEBaiEBDO0BCyAAQRQ2AhwgACAENgIMIAAgAUEBajYCFEEAIRAM9QELIBBBFUYNvQEgAEEANgIcIAAgATYCFCAAQZqPgIAANgIQIABBIjYCDEEAIRAM9AELIAAoAgQhECAAQQA2AgQCQCAAIBAgARC3gICAACIQDQAgAUEBaiEBDIYBCyAAQRY2AhwgACAQNgIMIAAgAUEBajYCFEEAIRAM8wELIAAoAgQhBCAAQQA2AgQCQCAAIAQgARC3gICAACIEDQAgAUEBaiEBDOkBCyAAQRc2AhwgACAENgIMIAAgAUEBajYCFEEAIRAM8gELIABBADYCHCAAIAE2AhQgAEHNk4CAADYCECAAQQw2AgxBACEQDPEBC0IBIRELIBBBAWohAQJAIAApAyAiEkL//////////w9WDQAgACASQgSGIBGENwMgIAEhAQyEAQsgAEEANgIcIAAgATYCFCAAQa2JgIAANgIQIABBDDYCDEEAIRAM7wELIABBADYCHCAAIBA2AhQgAEHNk4CAADYCECAAQQw2AgxBACEQDO4BCyAAKAIEIRcgAEEANgIEIBAgEadqIhYhASAAIBcgECAWIBQbIhAQtYCAgAAiFEUNcyAAQQU2AhwgACAQNgIUIAAgFDYCDEEAIRAM7QELIABBADYCHCAAIBA2AhQgAEGqnICAADYCECAAQQ82AgxBACEQDOwBCyAAIBAgAhC0gICAACIBDQEgECEBC0EOIRAM0QELAkAgAUEVRw0AIABBAjYCHCAAIBA2AhQgAEGwmICAADYCECAAQRU2AgxBACEQDOoBCyAAQQA2AhwgACAQNgIUIABBp46AgAA2AhAgAEESNgIMQQAhEAzpAQsgAUEBaiEQAkAgAC8BMCIBQYABcUUNAAJAIAAgECACELuAgIAAIgENACAQIQEMcAsgAUEVRw26ASAAQQU2AhwgACAQNgIUIABB+ZeAgAA2AhAgAEEVNgIMQQAhEAzpAQsCQCABQaAEcUGgBEcNACAALQAtQQJxDQAgAEEANgIcIAAgEDYCFCAAQZaTgIAANgIQIABBBDYCDEEAIRAM6QELIAAgECACEL2AgIAAGiAQIQECQAJAAkACQAJAIAAgECACELOAgIAADhYCAQAEBAQEBAQEBAQEBAQEBAQEBAQDBAsgAEEBOgAuCyAAIAAvATBBwAByOwEwIBAhAQtBJiEQDNEBCyAAQSM2AhwgACAQNgIUIABBpZaAgAA2AhAgAEEVNgIMQQAhEAzpAQsgAEEANgIcIAAgEDYCFCAAQdWLgIAANgIQIABBETYCDEEAIRAM6AELIAAtAC1BAXFFDQFBwwEhEAzOAQsCQCANIAJGDQADQAJAIA0tAABBIEYNACANIQEMxAELIA1BAWoiDSACRw0AC0ElIRAM5wELQSUhEAzmAQsgACgCBCEEIABBADYCBCAAIAQgDRCvgICAACIERQ2tASAAQSY2AhwgACAENgIMIAAgDUEBajYCFEEAIRAM5QELIBBBFUYNqwEgAEEANgIcIAAgATYCFCAAQf2NgIAANgIQIABBHTYCDEEAIRAM5AELIABBJzYCHCAAIAE2AhQgACAQNgIMQQAhEAzjAQsgECEBQQEhFAJAAkACQAJAAkACQAJAIAAtACxBfmoOBwYFBQMBAgAFCyAAIAAvATBBCHI7ATAMAwtBAiEUDAELQQQhFAsgAEEBOgAsIAAgAC8BMCAUcjsBMAsgECEBC0ErIRAMygELIABBADYCHCAAIBA2AhQgAEGrkoCAADYCECAAQQs2AgxBACEQDOIBCyAAQQA2AhwgACABNgIUIABB4Y+AgAA2AhAgAEEKNgIMQQAhEAzhAQsgAEEAOgAsIBAhAQy9AQsgECEBQQEhFAJAAkACQAJAAkAgAC0ALEF7ag4EAwECAAULIAAgAC8BMEEIcjsBMAwDC0ECIRQMAQtBBCEUCyAAQQE6ACwgACAALwEwIBRyOwEwCyAQIQELQSkhEAzFAQsgAEEANgIcIAAgATYCFCAAQfCUgIAANgIQIABBAzYCDEEAIRAM3QELAkAgDi0AAEENRw0AIAAoAgQhASAAQQA2AgQCQCAAIAEgDhCxgICAACIBDQAgDkEBaiEBDHULIABBLDYCHCAAIAE2AgwgACAOQQFqNgIUQQAhEAzdAQsgAC0ALUEBcUUNAUHEASEQDMMBCwJAIA4gAkcNAEEtIRAM3AELAkACQANAAkAgDi0AAEF2ag4EAgAAAwALIA5BAWoiDiACRw0AC0EtIRAM3QELIAAoAgQhASAAQQA2AgQCQCAAIAEgDhCxgICAACIBDQAgDiEBDHQLIABBLDYCHCAAIA42AhQgACABNgIMQQAhEAzcAQsgACgCBCEBIABBADYCBAJAIAAgASAOELGAgIAAIgENACAOQQFqIQEMcwsgAEEsNgIcIAAgATYCDCAAIA5BAWo2AhRBACEQDNsBCyAAKAIEIQQgAEEANgIEIAAgBCAOELGAgIAAIgQNoAEgDiEBDM4BCyAQQSxHDQEgAUEBaiEQQQEhAQJAAkACQAJAAkAgAC0ALEF7ag4EAwECBAALIBAhAQwEC0ECIQEMAQtBBCEBCyAAQQE6ACwgACAALwEwIAFyOwEwIBAhAQwBCyAAIAAvATBBCHI7ATAgECEBC0E5IRAMvwELIABBADoALCABIQELQTQhEAy9AQsgACAALwEwQSByOwEwIAEhAQwCCyAAKAIEIQQgAEEANgIEAkAgACAEIAEQsYCAgAAiBA0AIAEhAQzHAQsgAEE3NgIcIAAgATYCFCAAIAQ2AgxBACEQDNQBCyAAQQg6ACwgASEBC0EwIRAMuQELAkAgAC0AKEEBRg0AIAEhAQwECyAALQAtQQhxRQ2TASABIQEMAwsgAC0AMEEgcQ2UAUHFASEQDLcBCwJAIA8gAkYNAAJAA0ACQCAPLQAAQVBqIgFB/wFxQQpJDQAgDyEBQTUhEAy6AQsgACkDICIRQpmz5syZs+bMGVYNASAAIBFCCn4iETcDICARIAGtQv8BgyISQn+FVg0BIAAgESASfDcDICAPQQFqIg8gAkcNAAtBOSEQDNEBCyAAKAIEIQIgAEEANgIEIAAgAiAPQQFqIgQQsYCAgAAiAg2VASAEIQEMwwELQTkhEAzPAQsCQCAALwEwIgFBCHFFDQAgAC0AKEEBRw0AIAAtAC1BCHFFDZABCyAAIAFB9/sDcUGABHI7ATAgDyEBC0E3IRAMtAELIAAgAC8BMEEQcjsBMAyrAQsgEEEVRg2LASAAQQA2AhwgACABNgIUIABB8I6AgAA2AhAgAEEcNgIMQQAhEAzLAQsgAEHDADYCHCAAIAE2AgwgACANQQFqNgIUQQAhEAzKAQsCQCABLQAAQTpHDQAgACgCBCEQIABBADYCBAJAIAAgECABEK+AgIAAIhANACABQQFqIQEMYwsgAEHDADYCHCAAIBA2AgwgACABQQFqNgIUQQAhEAzKAQsgAEEANgIcIAAgATYCFCAAQbGRgIAANgIQIABBCjYCDEEAIRAMyQELIABBADYCHCAAIAE2AhQgAEGgmYCAADYCECAAQR42AgxBACEQDMgBCyAAQQA2AgALIABBgBI7ASogACAXQQFqIgEgAhCogICAACIQDQEgASEBC0HHACEQDKwBCyAQQRVHDYMBIABB0QA2AhwgACABNgIUIABB45eAgAA2AhAgAEEVNgIMQQAhEAzEAQsgACgCBCEQIABBADYCBAJAIAAgECABEKeAgIAAIhANACABIQEMXgsgAEHSADYCHCAAIAE2AhQgACAQNgIMQQAhEAzDAQsgAEEANgIcIAAgFDYCFCAAQcGogIAANgIQIABBBzYCDCAAQQA2AgBBACEQDMIBCyAAKAIEIRAgAEEANgIEAkAgACAQIAEQp4CAgAAiEA0AIAEhAQxdCyAAQdMANgIcIAAgATYCFCAAIBA2AgxBACEQDMEBC0EAIRAgAEEANgIcIAAgATYCFCAAQYCRgIAANgIQIABBCTYCDAzAAQsgEEEVRg19IABBADYCHCAAIAE2AhQgAEGUjYCAADYCECAAQSE2AgxBACEQDL8BC0EBIRZBACEXQQAhFEEBIRALIAAgEDoAKyABQQFqIQECQAJAIAAtAC1BEHENAAJAAkACQCAALQAqDgMBAAIECyAWRQ0DDAILIBQNAQwCCyAXRQ0BCyAAKAIEIRAgAEEANgIEAkAgACAQIAEQrYCAgAAiEA0AIAEhAQxcCyAAQdgANgIcIAAgATYCFCAAIBA2AgxBACEQDL4BCyAAKAIEIQQgAEEANgIEAkAgACAEIAEQrYCAgAAiBA0AIAEhAQytAQsgAEHZADYCHCAAIAE2AhQgACAENgIMQQAhEAy9AQsgACgCBCEEIABBADYCBAJAIAAgBCABEK2AgIAAIgQNACABIQEMqwELIABB2gA2AhwgACABNgIUIAAgBDYCDEEAIRAMvAELIAAoAgQhBCAAQQA2AgQCQCAAIAQgARCtgICAACIEDQAgASEBDKkBCyAAQdwANgIcIAAgATYCFCAAIAQ2AgxBACEQDLsBCwJAIAEtAABBUGoiEEH/AXFBCk8NACAAIBA6ACogAUEBaiEBQc8AIRAMogELIAAoAgQhBCAAQQA2AgQCQCAAIAQgARCtgICAACIEDQAgASEBDKcBCyAAQd4ANgIcIAAgATYCFCAAIAQ2AgxBACEQDLoBCyAAQQA2AgAgF0EBaiEBAkAgAC0AKUEjTw0AIAEhAQxZCyAAQQA2AhwgACABNgIUIABB04mAgAA2AhAgAEEINgIMQQAhEAy5AQsgAEEANgIAC0EAIRAgAEEANgIcIAAgATYCFCAAQZCzgIAANgIQIABBCDYCDAy3AQsgAEEANgIAIBdBAWohAQJAIAAtAClBIUcNACABIQEMVgsgAEEANgIcIAAgATYCFCAAQZuKgIAANgIQIABBCDYCDEEAIRAMtgELIABBADYCACAXQQFqIQECQCAALQApIhBBXWpBC08NACABIQEMVQsCQCAQQQZLDQBBASAQdEHKAHFFDQAgASEBDFULQQAhECAAQQA2AhwgACABNgIUIABB94mAgAA2AhAgAEEINgIMDLUBCyAQQRVGDXEgAEEANgIcIAAgATYCFCAAQbmNgIAANgIQIABBGjYCDEEAIRAMtAELIAAoAgQhECAAQQA2AgQCQCAAIBAgARCngICAACIQDQAgASEBDFQLIABB5QA2AhwgACABNgIUIAAgEDYCDEEAIRAMswELIAAoAgQhECAAQQA2AgQCQCAAIBAgARCngICAACIQDQAgASEBDE0LIABB0gA2AhwgACABNgIUIAAgEDYCDEEAIRAMsgELIAAoAgQhECAAQQA2AgQCQCAAIBAgARCngICAACIQDQAgASEBDE0LIABB0wA2AhwgACABNgIUIAAgEDYCDEEAIRAMsQELIAAoAgQhECAAQQA2AgQCQCAAIBAgARCngICAACIQDQAgASEBDFELIABB5QA2AhwgACABNgIUIAAgEDYCDEEAIRAMsAELIABBADYCHCAAIAE2AhQgAEHGioCAADYCECAAQQc2AgxBACEQDK8BCyAAKAIEIRAgAEEANgIEAkAgACAQIAEQp4CAgAAiEA0AIAEhAQxJCyAAQdIANgIcIAAgATYCFCAAIBA2AgxBACEQDK4BCyAAKAIEIRAgAEEANgIEAkAgACAQIAEQp4CAgAAiEA0AIAEhAQxJCyAAQdMANgIcIAAgATYCFCAAIBA2AgxBACEQDK0BCyAAKAIEIRAgAEEANgIEAkAgACAQIAEQp4CAgAAiEA0AIAEhAQxNCyAAQeUANgIcIAAgATYCFCAAIBA2AgxBACEQDKwBCyAAQQA2AhwgACABNgIUIABB3IiAgAA2AhAgAEEHNgIMQQAhEAyrAQsgEEE/Rw0BIAFBAWohAQtBBSEQDJABC0EAIRAgAEEANgIcIAAgATYCFCAAQf2SgIAANgIQIABBBzYCDAyoAQsgACgCBCEQIABBADYCBAJAIAAgECABEKeAgIAAIhANACABIQEMQgsgAEHSADYCHCAAIAE2AhQgACAQNgIMQQAhEAynAQsgACgCBCEQIABBADYCBAJAIAAgECABEKeAgIAAIhANACABIQEMQgsgAEHTADYCHCAAIAE2AhQgACAQNgIMQQAhEAymAQsgACgCBCEQIABBADYCBAJAIAAgECABEKeAgIAAIhANACABIQEMRgsgAEHlADYCHCAAIAE2AhQgACAQNgIMQQAhEAylAQsgACgCBCEBIABBADYCBAJAIAAgASAUEKeAgIAAIgENACAUIQEMPwsgAEHSADYCHCAAIBQ2AhQgACABNgIMQQAhEAykAQsgACgCBCEBIABBADYCBAJAIAAgASAUEKeAgIAAIgENACAUIQEMPwsgAEHTADYCHCAAIBQ2AhQgACABNgIMQQAhEAyjAQsgACgCBCEBIABBADYCBAJAIAAgASAUEKeAgIAAIgENACAUIQEMQwsgAEHlADYCHCAAIBQ2AhQgACABNgIMQQAhEAyiAQsgAEEANgIcIAAgFDYCFCAAQcOPgIAANgIQIABBBzYCDEEAIRAMoQELIABBADYCHCAAIAE2AhQgAEHDj4CAADYCECAAQQc2AgxBACEQDKABC0EAIRAgAEEANgIcIAAgFDYCFCAAQYycgIAANgIQIABBBzYCDAyfAQsgAEEANgIcIAAgFDYCFCAAQYycgIAANgIQIABBBzYCDEEAIRAMngELIABBADYCHCAAIBQ2AhQgAEH+kYCAADYCECAAQQc2AgxBACEQDJ0BCyAAQQA2AhwgACABNgIUIABBjpuAgAA2AhAgAEEGNgIMQQAhEAycAQsgEEEVRg1XIABBADYCHCAAIAE2AhQgAEHMjoCAADYCECAAQSA2AgxBACEQDJsBCyAAQQA2AgAgEEEBaiEBQSQhEAsgACAQOgApIAAoAgQhECAAQQA2AgQgACAQIAEQq4CAgAAiEA1UIAEhAQw+CyAAQQA2AgALQQAhECAAQQA2AhwgACAENgIUIABB8ZuAgAA2AhAgAEEGNgIMDJcBCyABQRVGDVAgAEEANgIcIAAgBTYCFCAAQfCMgIAANgIQIABBGzYCDEEAIRAMlgELIAAoAgQhBSAAQQA2AgQgACAFIBAQqYCAgAAiBQ0BIBBBAWohBQtBrQEhEAx7CyAAQcEBNgIcIAAgBTYCDCAAIBBBAWo2AhRBACEQDJMBCyAAKAIEIQYgAEEANgIEIAAgBiAQEKmAgIAAIgYNASAQQQFqIQYLQa4BIRAMeAsgAEHCATYCHCAAIAY2AgwgACAQQQFqNgIUQQAhEAyQAQsgAEEANgIcIAAgBzYCFCAAQZeLgIAANgIQIABBDTYCDEEAIRAMjwELIABBADYCHCAAIAg2AhQgAEHjkICAADYCECAAQQk2AgxBACEQDI4BCyAAQQA2AhwgACAINgIUIABBlI2AgAA2AhAgAEEhNgIMQQAhEAyNAQtBASEWQQAhF0EAIRRBASEQCyAAIBA6ACsgCUEBaiEIAkACQCAALQAtQRBxDQACQAJAAkAgAC0AKg4DAQACBAsgFkUNAwwCCyAUDQEMAgsgF0UNAQsgACgCBCEQIABBADYCBCAAIBAgCBCtgICAACIQRQ09IABByQE2AhwgACAINgIUIAAgEDYCDEEAIRAMjAELIAAoAgQhBCAAQQA2AgQgACAEIAgQrYCAgAAiBEUNdiAAQcoBNgIcIAAgCDYCFCAAIAQ2AgxBACEQDIsBCyAAKAIEIQQgAEEANgIEIAAgBCAJEK2AgIAAIgRFDXQgAEHLATYCHCAAIAk2AhQgACAENgIMQQAhEAyKAQsgACgCBCEEIABBADYCBCAAIAQgChCtgICAACIERQ1yIABBzQE2AhwgACAKNgIUIAAgBDYCDEEAIRAMiQELAkAgCy0AAEFQaiIQQf8BcUEKTw0AIAAgEDoAKiALQQFqIQpBtgEhEAxwCyAAKAIEIQQgAEEANgIEIAAgBCALEK2AgIAAIgRFDXAgAEHPATYCHCAAIAs2AhQgACAENgIMQQAhEAyIAQsgAEEANgIcIAAgBDYCFCAAQZCzgIAANgIQIABBCDYCDCAAQQA2AgBBACEQDIcBCyABQRVGDT8gAEEANgIcIAAgDDYCFCAAQcyOgIAANgIQIABBIDYCDEEAIRAMhgELIABBgQQ7ASggACgCBCEQIABCADcDACAAIBAgDEEBaiIMEKuAgIAAIhBFDTggAEHTATYCHCAAIAw2AhQgACAQNgIMQQAhEAyFAQsgAEEANgIAC0EAIRAgAEEANgIcIAAgBDYCFCAAQdibgIAANgIQIABBCDYCDAyDAQsgACgCBCEQIABCADcDACAAIBAgC0EBaiILEKuAgIAAIhANAUHGASEQDGkLIABBAjoAKAxVCyAAQdUBNgIcIAAgCzYCFCAAIBA2AgxBACEQDIABCyAQQRVGDTcgAEEANgIcIAAgBDYCFCAAQaSMgIAANgIQIABBEDYCDEEAIRAMfwsgAC0ANEEBRw00IAAgBCACELyAgIAAIhBFDTQgEEEVRw01IABB3AE2AhwgACAENgIUIABB1ZaAgAA2AhAgAEEVNgIMQQAhEAx+C0EAIRAgAEEANgIcIABBr4uAgAA2AhAgAEECNgIMIAAgFEEBajYCFAx9C0EAIRAMYwtBAiEQDGILQQ0hEAxhC0EPIRAMYAtBJSEQDF8LQRMhEAxeC0EVIRAMXQtBFiEQDFwLQRchEAxbC0EYIRAMWgtBGSEQDFkLQRohEAxYC0EbIRAMVwtBHCEQDFYLQR0hEAxVC0EfIRAMVAtBISEQDFMLQSMhEAxSC0HGACEQDFELQS4hEAxQC0EvIRAMTwtBOyEQDE4LQT0hEAxNC0HIACEQDEwLQckAIRAMSwtBywAhEAxKC0HMACEQDEkLQc4AIRAMSAtB0QAhEAxHC0HVACEQDEYLQdgAIRAMRQtB2QAhEAxEC0HbACEQDEMLQeQAIRAMQgtB5QAhEAxBC0HxACEQDEALQfQAIRAMPwtBjQEhEAw+C0GXASEQDD0LQakBIRAMPAtBrAEhEAw7C0HAASEQDDoLQbkBIRAMOQtBrwEhEAw4C0GxASEQDDcLQbIBIRAMNgtBtAEhEAw1C0G1ASEQDDQLQboBIRAMMwtBvQEhEAwyC0G/ASEQDDELQcEBIRAMMAsgAEEANgIcIAAgBDYCFCAAQemLgIAANgIQIABBHzYCDEEAIRAMSAsgAEHbATYCHCAAIAQ2AhQgAEH6loCAADYCECAAQRU2AgxBACEQDEcLIABB+AA2AhwgACAMNgIUIABBypiAgAA2AhAgAEEVNgIMQQAhEAxGCyAAQdEANgIcIAAgBTYCFCAAQbCXgIAANgIQIABBFTYCDEEAIRAMRQsgAEH5ADYCHCAAIAE2AhQgACAQNgIMQQAhEAxECyAAQfgANgIcIAAgATYCFCAAQcqYgIAANgIQIABBFTYCDEEAIRAMQwsgAEHkADYCHCAAIAE2AhQgAEHjl4CAADYCECAAQRU2AgxBACEQDEILIABB1wA2AhwgACABNgIUIABByZeAgAA2AhAgAEEVNgIMQQAhEAxBCyAAQQA2AhwgACABNgIUIABBuY2AgAA2AhAgAEEaNgIMQQAhEAxACyAAQcIANgIcIAAgATYCFCAAQeOYgIAANgIQIABBFTYCDEEAIRAMPwsgAEEANgIEIAAgDyAPELGAgIAAIgRFDQEgAEE6NgIcIAAgBDYCDCAAIA9BAWo2AhRBACEQDD4LIAAoAgQhBCAAQQA2AgQCQCAAIAQgARCxgICAACIERQ0AIABBOzYCHCAAIAQ2AgwgACABQQFqNgIUQQAhEAw+CyABQQFqIQEMLQsgD0EBaiEBDC0LIABBADYCHCAAIA82AhQgAEHkkoCAADYCECAAQQQ2AgxBACEQDDsLIABBNjYCHCAAIAQ2AhQgACACNgIMQQAhEAw6CyAAQS42AhwgACAONgIUIAAgBDYCDEEAIRAMOQsgAEHQADYCHCAAIAE2AhQgAEGRmICAADYCECAAQRU2AgxBACEQDDgLIA1BAWohAQwsCyAAQRU2AhwgACABNgIUIABBgpmAgAA2AhAgAEEVNgIMQQAhEAw2CyAAQRs2AhwgACABNgIUIABBkZeAgAA2AhAgAEEVNgIMQQAhEAw1CyAAQQ82AhwgACABNgIUIABBkZeAgAA2AhAgAEEVNgIMQQAhEAw0CyAAQQs2AhwgACABNgIUIABBkZeAgAA2AhAgAEEVNgIMQQAhEAwzCyAAQRo2AhwgACABNgIUIABBgpmAgAA2AhAgAEEVNgIMQQAhEAwyCyAAQQs2AhwgACABNgIUIABBgpmAgAA2AhAgAEEVNgIMQQAhEAwxCyAAQQo2AhwgACABNgIUIABB5JaAgAA2AhAgAEEVNgIMQQAhEAwwCyAAQR42AhwgACABNgIUIABB+ZeAgAA2AhAgAEEVNgIMQQAhEAwvCyAAQQA2AhwgACAQNgIUIABB2o2AgAA2AhAgAEEUNgIMQQAhEAwuCyAAQQQ2AhwgACABNgIUIABBsJiAgAA2AhAgAEEVNgIMQQAhEAwtCyAAQQA2AgAgC0EBaiELC0G4ASEQDBILIABBADYCACAQQQFqIQFB9QAhEAwRCyABIQECQCAALQApQQVHDQBB4wAhEAwRC0HiACEQDBALQQAhECAAQQA2AhwgAEHkkYCAADYCECAAQQc2AgwgACAUQQFqNgIUDCgLIABBADYCACAXQQFqIQFBwAAhEAwOC0EBIQELIAAgAToALCAAQQA2AgAgF0EBaiEBC0EoIRAMCwsgASEBC0E4IRAMCQsCQCABIg8gAkYNAANAAkAgDy0AAEGAvoCAAGotAAAiAUEBRg0AIAFBAkcNAyAPQQFqIQEMBAsgD0EBaiIPIAJHDQALQT4hEAwiC0E+IRAMIQsgAEEAOgAsIA8hAQwBC0ELIRAMBgtBOiEQDAULIAFBAWohAUEtIRAMBAsgACABOgAsIABBADYCACAWQQFqIQFBDCEQDAMLIABBADYCACAXQQFqIQFBCiEQDAILIABBADYCAAsgAEEAOgAsIA0hAUEJIRAMAAsLQQAhECAAQQA2AhwgACALNgIUIABBzZCAgAA2AhAgAEEJNgIMDBcLQQAhECAAQQA2AhwgACAKNgIUIABB6YqAgAA2AhAgAEEJNgIMDBYLQQAhECAAQQA2AhwgACAJNgIUIABBt5CAgAA2AhAgAEEJNgIMDBULQQAhECAAQQA2AhwgACAINgIUIABBnJGAgAA2AhAgAEEJNgIMDBQLQQAhECAAQQA2AhwgACABNgIUIABBzZCAgAA2AhAgAEEJNgIMDBMLQQAhECAAQQA2AhwgACABNgIUIABB6YqAgAA2AhAgAEEJNgIMDBILQQAhECAAQQA2AhwgACABNgIUIABBt5CAgAA2AhAgAEEJNgIMDBELQQAhECAAQQA2AhwgACABNgIUIABBnJGAgAA2AhAgAEEJNgIMDBALQQAhECAAQQA2AhwgACABNgIUIABBl5WAgAA2AhAgAEEPNgIMDA8LQQAhECAAQQA2AhwgACABNgIUIABBl5WAgAA2AhAgAEEPNgIMDA4LQQAhECAAQQA2AhwgACABNgIUIABBwJKAgAA2AhAgAEELNgIMDA0LQQAhECAAQQA2AhwgACABNgIUIABBlYmAgAA2AhAgAEELNgIMDAwLQQAhECAAQQA2AhwgACABNgIUIABB4Y+AgAA2AhAgAEEKNgIMDAsLQQAhECAAQQA2AhwgACABNgIUIABB+4+AgAA2AhAgAEEKNgIMDAoLQQAhECAAQQA2AhwgACABNgIUIABB8ZmAgAA2AhAgAEECNgIMDAkLQQAhECAAQQA2AhwgACABNgIUIABBxJSAgAA2AhAgAEECNgIMDAgLQQAhECAAQQA2AhwgACABNgIUIABB8pWAgAA2AhAgAEECNgIMDAcLIABBAjYCHCAAIAE2AhQgAEGcmoCAADYCECAAQRY2AgxBACEQDAYLQQEhEAwFC0HUACEQIAEiBCACRg0EIANBCGogACAEIAJB2MKAgABBChDFgICAACADKAIMIQQgAygCCA4DAQQCAAsQyoCAgAAACyAAQQA2AhwgAEG1moCAADYCECAAQRc2AgwgACAEQQFqNgIUQQAhEAwCCyAAQQA2AhwgACAENgIUIABBypqAgAA2AhAgAEEJNgIMQQAhEAwBCwJAIAEiBCACRw0AQSIhEAwBCyAAQYmAgIAANgIIIAAgBDYCBEEhIRALIANBEGokgICAgAAgEAuvAQECfyABKAIAIQYCQAJAIAIgA0YNACAEIAZqIQQgBiADaiACayEHIAIgBkF/cyAFaiIGaiEFA0ACQCACLQAAIAQtAABGDQBBAiEEDAMLAkAgBg0AQQAhBCAFIQIMAwsgBkF/aiEGIARBAWohBCACQQFqIgIgA0cNAAsgByEGIAMhAgsgAEEBNgIAIAEgBjYCACAAIAI2AgQPCyABQQA2AgAgACAENgIAIAAgAjYCBAsKACAAEMeAgIAAC/I2AQt/I4CAgIAAQRBrIgEkgICAgAACQEEAKAKg0ICAAA0AQQAQy4CAgABBgNSEgABrIgJB2QBJDQBBACEDAkBBACgC4NOAgAAiBA0AQQBCfzcC7NOAgABBAEKAgISAgIDAADcC5NOAgABBACABQQhqQXBxQdiq1aoFcyIENgLg04CAAEEAQQA2AvTTgIAAQQBBADYCxNOAgAALQQAgAjYCzNOAgABBAEGA1ISAADYCyNOAgABBAEGA1ISAADYCmNCAgABBACAENgKs0ICAAEEAQX82AqjQgIAAA0AgA0HE0ICAAGogA0G40ICAAGoiBDYCACAEIANBsNCAgABqIgU2AgAgA0G80ICAAGogBTYCACADQczQgIAAaiADQcDQgIAAaiIFNgIAIAUgBDYCACADQdTQgIAAaiADQcjQgIAAaiIENgIAIAQgBTYCACADQdDQgIAAaiAENgIAIANBIGoiA0GAAkcNAAtBgNSEgABBeEGA1ISAAGtBD3FBAEGA1ISAAEEIakEPcRsiA2oiBEEEaiACQUhqIgUgA2siA0EBcjYCAEEAQQAoAvDTgIAANgKk0ICAAEEAIAM2ApTQgIAAQQAgBDYCoNCAgABBgNSEgAAgBWpBODYCBAsCQAJAAkACQAJAAkACQAJAAkACQAJAAkAgAEHsAUsNAAJAQQAoAojQgIAAIgZBECAAQRNqQXBxIABBC0kbIgJBA3YiBHYiA0EDcUUNAAJAAkAgA0EBcSAEckEBcyIFQQN0IgRBsNCAgABqIgMgBEG40ICAAGooAgAiBCgCCCICRw0AQQAgBkF+IAV3cTYCiNCAgAAMAQsgAyACNgIIIAIgAzYCDAsgBEEIaiEDIAQgBUEDdCIFQQNyNgIEIAQgBWoiBCAEKAIEQQFyNgIEDAwLIAJBACgCkNCAgAAiB00NAQJAIANFDQACQAJAIAMgBHRBAiAEdCIDQQAgA2tycSIDQQAgA2txQX9qIgMgA0EMdkEQcSIDdiIEQQV2QQhxIgUgA3IgBCAFdiIDQQJ2QQRxIgRyIAMgBHYiA0EBdkECcSIEciADIAR2IgNBAXZBAXEiBHIgAyAEdmoiBEEDdCIDQbDQgIAAaiIFIANBuNCAgABqKAIAIgMoAggiAEcNAEEAIAZBfiAEd3EiBjYCiNCAgAAMAQsgBSAANgIIIAAgBTYCDAsgAyACQQNyNgIEIAMgBEEDdCIEaiAEIAJrIgU2AgAgAyACaiIAIAVBAXI2AgQCQCAHRQ0AIAdBeHFBsNCAgABqIQJBACgCnNCAgAAhBAJAAkAgBkEBIAdBA3Z0IghxDQBBACAGIAhyNgKI0ICAACACIQgMAQsgAigCCCEICyAIIAQ2AgwgAiAENgIIIAQgAjYCDCAEIAg2AggLIANBCGohA0EAIAA2ApzQgIAAQQAgBTYCkNCAgAAMDAtBACgCjNCAgAAiCUUNASAJQQAgCWtxQX9qIgMgA0EMdkEQcSIDdiIEQQV2QQhxIgUgA3IgBCAFdiIDQQJ2QQRxIgRyIAMgBHYiA0EBdkECcSIEciADIAR2IgNBAXZBAXEiBHIgAyAEdmpBAnRBuNKAgABqKAIAIgAoAgRBeHEgAmshBCAAIQUCQANAAkAgBSgCECIDDQAgBUEUaigCACIDRQ0CCyADKAIEQXhxIAJrIgUgBCAFIARJIgUbIQQgAyAAIAUbIQAgAyEFDAALCyAAKAIYIQoCQCAAKAIMIgggAEYNACAAKAIIIgNBACgCmNCAgABJGiAIIAM2AgggAyAINgIMDAsLAkAgAEEUaiIFKAIAIgMNACAAKAIQIgNFDQMgAEEQaiEFCwNAIAUhCyADIghBFGoiBSgCACIDDQAgCEEQaiEFIAgoAhAiAw0ACyALQQA2AgAMCgtBfyECIABBv39LDQAgAEETaiIDQXBxIQJBACgCjNCAgAAiB0UNAEEAIQsCQCACQYACSQ0AQR8hCyACQf///wdLDQAgA0EIdiIDIANBgP4/akEQdkEIcSIDdCIEIARBgOAfakEQdkEEcSIEdCIFIAVBgIAPakEQdkECcSIFdEEPdiADIARyIAVyayIDQQF0IAIgA0EVanZBAXFyQRxqIQsLQQAgAmshBAJAAkACQAJAIAtBAnRBuNKAgABqKAIAIgUNAEEAIQNBACEIDAELQQAhAyACQQBBGSALQQF2ayALQR9GG3QhAEEAIQgDQAJAIAUoAgRBeHEgAmsiBiAETw0AIAYhBCAFIQggBg0AQQAhBCAFIQggBSEDDAMLIAMgBUEUaigCACIGIAYgBSAAQR12QQRxakEQaigCACIFRhsgAyAGGyEDIABBAXQhACAFDQALCwJAIAMgCHINAEEAIQhBAiALdCIDQQAgA2tyIAdxIgNFDQMgA0EAIANrcUF/aiIDIANBDHZBEHEiA3YiBUEFdkEIcSIAIANyIAUgAHYiA0ECdkEEcSIFciADIAV2IgNBAXZBAnEiBXIgAyAFdiIDQQF2QQFxIgVyIAMgBXZqQQJ0QbjSgIAAaigCACEDCyADRQ0BCwNAIAMoAgRBeHEgAmsiBiAESSEAAkAgAygCECIFDQAgA0EUaigCACEFCyAGIAQgABshBCADIAggABshCCAFIQMgBQ0ACwsgCEUNACAEQQAoApDQgIAAIAJrTw0AIAgoAhghCwJAIAgoAgwiACAIRg0AIAgoAggiA0EAKAKY0ICAAEkaIAAgAzYCCCADIAA2AgwMCQsCQCAIQRRqIgUoAgAiAw0AIAgoAhAiA0UNAyAIQRBqIQULA0AgBSEGIAMiAEEUaiIFKAIAIgMNACAAQRBqIQUgACgCECIDDQALIAZBADYCAAwICwJAQQAoApDQgIAAIgMgAkkNAEEAKAKc0ICAACEEAkACQCADIAJrIgVBEEkNACAEIAJqIgAgBUEBcjYCBEEAIAU2ApDQgIAAQQAgADYCnNCAgAAgBCADaiAFNgIAIAQgAkEDcjYCBAwBCyAEIANBA3I2AgQgBCADaiIDIAMoAgRBAXI2AgRBAEEANgKc0ICAAEEAQQA2ApDQgIAACyAEQQhqIQMMCgsCQEEAKAKU0ICAACIAIAJNDQBBACgCoNCAgAAiAyACaiIEIAAgAmsiBUEBcjYCBEEAIAU2ApTQgIAAQQAgBDYCoNCAgAAgAyACQQNyNgIEIANBCGohAwwKCwJAAkBBACgC4NOAgABFDQBBACgC6NOAgAAhBAwBC0EAQn83AuzTgIAAQQBCgICEgICAwAA3AuTTgIAAQQAgAUEMakFwcUHYqtWqBXM2AuDTgIAAQQBBADYC9NOAgABBAEEANgLE04CAAEGAgAQhBAtBACEDAkAgBCACQccAaiIHaiIGQQAgBGsiC3EiCCACSw0AQQBBMDYC+NOAgAAMCgsCQEEAKALA04CAACIDRQ0AAkBBACgCuNOAgAAiBCAIaiIFIARNDQAgBSADTQ0BC0EAIQNBAEEwNgL404CAAAwKC0EALQDE04CAAEEEcQ0EAkACQAJAQQAoAqDQgIAAIgRFDQBByNOAgAAhAwNAAkAgAygCACIFIARLDQAgBSADKAIEaiAESw0DCyADKAIIIgMNAAsLQQAQy4CAgAAiAEF/Rg0FIAghBgJAQQAoAuTTgIAAIgNBf2oiBCAAcUUNACAIIABrIAQgAGpBACADa3FqIQYLIAYgAk0NBSAGQf7///8HSw0FAkBBACgCwNOAgAAiA0UNAEEAKAK404CAACIEIAZqIgUgBE0NBiAFIANLDQYLIAYQy4CAgAAiAyAARw0BDAcLIAYgAGsgC3EiBkH+////B0sNBCAGEMuAgIAAIgAgAygCACADKAIEakYNAyAAIQMLAkAgA0F/Rg0AIAJByABqIAZNDQACQCAHIAZrQQAoAujTgIAAIgRqQQAgBGtxIgRB/v///wdNDQAgAyEADAcLAkAgBBDLgICAAEF/Rg0AIAQgBmohBiADIQAMBwtBACAGaxDLgICAABoMBAsgAyEAIANBf0cNBQwDC0EAIQgMBwtBACEADAULIABBf0cNAgtBAEEAKALE04CAAEEEcjYCxNOAgAALIAhB/v///wdLDQEgCBDLgICAACEAQQAQy4CAgAAhAyAAQX9GDQEgA0F/Rg0BIAAgA08NASADIABrIgYgAkE4ak0NAQtBAEEAKAK404CAACAGaiIDNgK404CAAAJAIANBACgCvNOAgABNDQBBACADNgK804CAAAsCQAJAAkACQEEAKAKg0ICAACIERQ0AQcjTgIAAIQMDQCAAIAMoAgAiBSADKAIEIghqRg0CIAMoAggiAw0ADAMLCwJAAkBBACgCmNCAgAAiA0UNACAAIANPDQELQQAgADYCmNCAgAALQQAhA0EAIAY2AszTgIAAQQAgADYCyNOAgABBAEF/NgKo0ICAAEEAQQAoAuDTgIAANgKs0ICAAEEAQQA2AtTTgIAAA0AgA0HE0ICAAGogA0G40ICAAGoiBDYCACAEIANBsNCAgABqIgU2AgAgA0G80ICAAGogBTYCACADQczQgIAAaiADQcDQgIAAaiIFNgIAIAUgBDYCACADQdTQgIAAaiADQcjQgIAAaiIENgIAIAQgBTYCACADQdDQgIAAaiAENgIAIANBIGoiA0GAAkcNAAsgAEF4IABrQQ9xQQAgAEEIakEPcRsiA2oiBCAGQUhqIgUgA2siA0EBcjYCBEEAQQAoAvDTgIAANgKk0ICAAEEAIAM2ApTQgIAAQQAgBDYCoNCAgAAgACAFakE4NgIEDAILIAMtAAxBCHENACAEIAVJDQAgBCAATw0AIARBeCAEa0EPcUEAIARBCGpBD3EbIgVqIgBBACgClNCAgAAgBmoiCyAFayIFQQFyNgIEIAMgCCAGajYCBEEAQQAoAvDTgIAANgKk0ICAAEEAIAU2ApTQgIAAQQAgADYCoNCAgAAgBCALakE4NgIEDAELAkAgAEEAKAKY0ICAACIITw0AQQAgADYCmNCAgAAgACEICyAAIAZqIQVByNOAgAAhAwJAAkACQAJAAkACQAJAA0AgAygCACAFRg0BIAMoAggiAw0ADAILCyADLQAMQQhxRQ0BC0HI04CAACEDA0ACQCADKAIAIgUgBEsNACAFIAMoAgRqIgUgBEsNAwsgAygCCCEDDAALCyADIAA2AgAgAyADKAIEIAZqNgIEIABBeCAAa0EPcUEAIABBCGpBD3EbaiILIAJBA3I2AgQgBUF4IAVrQQ9xQQAgBUEIakEPcRtqIgYgCyACaiICayEDAkAgBiAERw0AQQAgAjYCoNCAgABBAEEAKAKU0ICAACADaiIDNgKU0ICAACACIANBAXI2AgQMAwsCQCAGQQAoApzQgIAARw0AQQAgAjYCnNCAgABBAEEAKAKQ0ICAACADaiIDNgKQ0ICAACACIANBAXI2AgQgAiADaiADNgIADAMLAkAgBigCBCIEQQNxQQFHDQAgBEF4cSEHAkACQCAEQf8BSw0AIAYoAggiBSAEQQN2IghBA3RBsNCAgABqIgBGGgJAIAYoAgwiBCAFRw0AQQBBACgCiNCAgABBfiAId3E2AojQgIAADAILIAQgAEYaIAQgBTYCCCAFIAQ2AgwMAQsgBigCGCEJAkACQCAGKAIMIgAgBkYNACAGKAIIIgQgCEkaIAAgBDYCCCAEIAA2AgwMAQsCQCAGQRRqIgQoAgAiBQ0AIAZBEGoiBCgCACIFDQBBACEADAELA0AgBCEIIAUiAEEUaiIEKAIAIgUNACAAQRBqIQQgACgCECIFDQALIAhBADYCAAsgCUUNAAJAAkAgBiAGKAIcIgVBAnRBuNKAgABqIgQoAgBHDQAgBCAANgIAIAANAUEAQQAoAozQgIAAQX4gBXdxNgKM0ICAAAwCCyAJQRBBFCAJKAIQIAZGG2ogADYCACAARQ0BCyAAIAk2AhgCQCAGKAIQIgRFDQAgACAENgIQIAQgADYCGAsgBigCFCIERQ0AIABBFGogBDYCACAEIAA2AhgLIAcgA2ohAyAGIAdqIgYoAgQhBAsgBiAEQX5xNgIEIAIgA2ogAzYCACACIANBAXI2AgQCQCADQf8BSw0AIANBeHFBsNCAgABqIQQCQAJAQQAoAojQgIAAIgVBASADQQN2dCIDcQ0AQQAgBSADcjYCiNCAgAAgBCEDDAELIAQoAgghAwsgAyACNgIMIAQgAjYCCCACIAQ2AgwgAiADNgIIDAMLQR8hBAJAIANB////B0sNACADQQh2IgQgBEGA/j9qQRB2QQhxIgR0IgUgBUGA4B9qQRB2QQRxIgV0IgAgAEGAgA9qQRB2QQJxIgB0QQ92IAQgBXIgAHJrIgRBAXQgAyAEQRVqdkEBcXJBHGohBAsgAiAENgIcIAJCADcCECAEQQJ0QbjSgIAAaiEFAkBBACgCjNCAgAAiAEEBIAR0IghxDQAgBSACNgIAQQAgACAIcjYCjNCAgAAgAiAFNgIYIAIgAjYCCCACIAI2AgwMAwsgA0EAQRkgBEEBdmsgBEEfRht0IQQgBSgCACEAA0AgACIFKAIEQXhxIANGDQIgBEEddiEAIARBAXQhBCAFIABBBHFqQRBqIggoAgAiAA0ACyAIIAI2AgAgAiAFNgIYIAIgAjYCDCACIAI2AggMAgsgAEF4IABrQQ9xQQAgAEEIakEPcRsiA2oiCyAGQUhqIgggA2siA0EBcjYCBCAAIAhqQTg2AgQgBCAFQTcgBWtBD3FBACAFQUlqQQ9xG2pBQWoiCCAIIARBEGpJGyIIQSM2AgRBAEEAKALw04CAADYCpNCAgABBACADNgKU0ICAAEEAIAs2AqDQgIAAIAhBEGpBACkC0NOAgAA3AgAgCEEAKQLI04CAADcCCEEAIAhBCGo2AtDTgIAAQQAgBjYCzNOAgABBACAANgLI04CAAEEAQQA2AtTTgIAAIAhBJGohAwNAIANBBzYCACADQQRqIgMgBUkNAAsgCCAERg0DIAggCCgCBEF+cTYCBCAIIAggBGsiADYCACAEIABBAXI2AgQCQCAAQf8BSw0AIABBeHFBsNCAgABqIQMCQAJAQQAoAojQgIAAIgVBASAAQQN2dCIAcQ0AQQAgBSAAcjYCiNCAgAAgAyEFDAELIAMoAgghBQsgBSAENgIMIAMgBDYCCCAEIAM2AgwgBCAFNgIIDAQLQR8hAwJAIABB////B0sNACAAQQh2IgMgA0GA/j9qQRB2QQhxIgN0IgUgBUGA4B9qQRB2QQRxIgV0IgggCEGAgA9qQRB2QQJxIgh0QQ92IAMgBXIgCHJrIgNBAXQgACADQRVqdkEBcXJBHGohAwsgBCADNgIcIARCADcCECADQQJ0QbjSgIAAaiEFAkBBACgCjNCAgAAiCEEBIAN0IgZxDQAgBSAENgIAQQAgCCAGcjYCjNCAgAAgBCAFNgIYIAQgBDYCCCAEIAQ2AgwMBAsgAEEAQRkgA0EBdmsgA0EfRht0IQMgBSgCACEIA0AgCCIFKAIEQXhxIABGDQMgA0EddiEIIANBAXQhAyAFIAhBBHFqQRBqIgYoAgAiCA0ACyAGIAQ2AgAgBCAFNgIYIAQgBDYCDCAEIAQ2AggMAwsgBSgCCCIDIAI2AgwgBSACNgIIIAJBADYCGCACIAU2AgwgAiADNgIICyALQQhqIQMMBQsgBSgCCCIDIAQ2AgwgBSAENgIIIARBADYCGCAEIAU2AgwgBCADNgIIC0EAKAKU0ICAACIDIAJNDQBBACgCoNCAgAAiBCACaiIFIAMgAmsiA0EBcjYCBEEAIAM2ApTQgIAAQQAgBTYCoNCAgAAgBCACQQNyNgIEIARBCGohAwwDC0EAIQNBAEEwNgL404CAAAwCCwJAIAtFDQACQAJAIAggCCgCHCIFQQJ0QbjSgIAAaiIDKAIARw0AIAMgADYCACAADQFBACAHQX4gBXdxIgc2AozQgIAADAILIAtBEEEUIAsoAhAgCEYbaiAANgIAIABFDQELIAAgCzYCGAJAIAgoAhAiA0UNACAAIAM2AhAgAyAANgIYCyAIQRRqKAIAIgNFDQAgAEEUaiADNgIAIAMgADYCGAsCQAJAIARBD0sNACAIIAQgAmoiA0EDcjYCBCAIIANqIgMgAygCBEEBcjYCBAwBCyAIIAJqIgAgBEEBcjYCBCAIIAJBA3I2AgQgACAEaiAENgIAAkAgBEH/AUsNACAEQXhxQbDQgIAAaiEDAkACQEEAKAKI0ICAACIFQQEgBEEDdnQiBHENAEEAIAUgBHI2AojQgIAAIAMhBAwBCyADKAIIIQQLIAQgADYCDCADIAA2AgggACADNgIMIAAgBDYCCAwBC0EfIQMCQCAEQf///wdLDQAgBEEIdiIDIANBgP4/akEQdkEIcSIDdCIFIAVBgOAfakEQdkEEcSIFdCICIAJBgIAPakEQdkECcSICdEEPdiADIAVyIAJyayIDQQF0IAQgA0EVanZBAXFyQRxqIQMLIAAgAzYCHCAAQgA3AhAgA0ECdEG40oCAAGohBQJAIAdBASADdCICcQ0AIAUgADYCAEEAIAcgAnI2AozQgIAAIAAgBTYCGCAAIAA2AgggACAANgIMDAELIARBAEEZIANBAXZrIANBH0YbdCEDIAUoAgAhAgJAA0AgAiIFKAIEQXhxIARGDQEgA0EddiECIANBAXQhAyAFIAJBBHFqQRBqIgYoAgAiAg0ACyAGIAA2AgAgACAFNgIYIAAgADYCDCAAIAA2AggMAQsgBSgCCCIDIAA2AgwgBSAANgIIIABBADYCGCAAIAU2AgwgACADNgIICyAIQQhqIQMMAQsCQCAKRQ0AAkACQCAAIAAoAhwiBUECdEG40oCAAGoiAygCAEcNACADIAg2AgAgCA0BQQAgCUF+IAV3cTYCjNCAgAAMAgsgCkEQQRQgCigCECAARhtqIAg2AgAgCEUNAQsgCCAKNgIYAkAgACgCECIDRQ0AIAggAzYCECADIAg2AhgLIABBFGooAgAiA0UNACAIQRRqIAM2AgAgAyAINgIYCwJAAkAgBEEPSw0AIAAgBCACaiIDQQNyNgIEIAAgA2oiAyADKAIEQQFyNgIEDAELIAAgAmoiBSAEQQFyNgIEIAAgAkEDcjYCBCAFIARqIAQ2AgACQCAHRQ0AIAdBeHFBsNCAgABqIQJBACgCnNCAgAAhAwJAAkBBASAHQQN2dCIIIAZxDQBBACAIIAZyNgKI0ICAACACIQgMAQsgAigCCCEICyAIIAM2AgwgAiADNgIIIAMgAjYCDCADIAg2AggLQQAgBTYCnNCAgABBACAENgKQ0ICAAAsgAEEIaiEDCyABQRBqJICAgIAAIAMLCgAgABDJgICAAAviDQEHfwJAIABFDQAgAEF4aiIBIABBfGooAgAiAkF4cSIAaiEDAkAgAkEBcQ0AIAJBA3FFDQEgASABKAIAIgJrIgFBACgCmNCAgAAiBEkNASACIABqIQACQCABQQAoApzQgIAARg0AAkAgAkH/AUsNACABKAIIIgQgAkEDdiIFQQN0QbDQgIAAaiIGRhoCQCABKAIMIgIgBEcNAEEAQQAoAojQgIAAQX4gBXdxNgKI0ICAAAwDCyACIAZGGiACIAQ2AgggBCACNgIMDAILIAEoAhghBwJAAkAgASgCDCIGIAFGDQAgASgCCCICIARJGiAGIAI2AgggAiAGNgIMDAELAkAgAUEUaiICKAIAIgQNACABQRBqIgIoAgAiBA0AQQAhBgwBCwNAIAIhBSAEIgZBFGoiAigCACIEDQAgBkEQaiECIAYoAhAiBA0ACyAFQQA2AgALIAdFDQECQAJAIAEgASgCHCIEQQJ0QbjSgIAAaiICKAIARw0AIAIgBjYCACAGDQFBAEEAKAKM0ICAAEF+IAR3cTYCjNCAgAAMAwsgB0EQQRQgBygCECABRhtqIAY2AgAgBkUNAgsgBiAHNgIYAkAgASgCECICRQ0AIAYgAjYCECACIAY2AhgLIAEoAhQiAkUNASAGQRRqIAI2AgAgAiAGNgIYDAELIAMoAgQiAkEDcUEDRw0AIAMgAkF+cTYCBEEAIAA2ApDQgIAAIAEgAGogADYCACABIABBAXI2AgQPCyABIANPDQAgAygCBCICQQFxRQ0AAkACQCACQQJxDQACQCADQQAoAqDQgIAARw0AQQAgATYCoNCAgABBAEEAKAKU0ICAACAAaiIANgKU0ICAACABIABBAXI2AgQgAUEAKAKc0ICAAEcNA0EAQQA2ApDQgIAAQQBBADYCnNCAgAAPCwJAIANBACgCnNCAgABHDQBBACABNgKc0ICAAEEAQQAoApDQgIAAIABqIgA2ApDQgIAAIAEgAEEBcjYCBCABIABqIAA2AgAPCyACQXhxIABqIQACQAJAIAJB/wFLDQAgAygCCCIEIAJBA3YiBUEDdEGw0ICAAGoiBkYaAkAgAygCDCICIARHDQBBAEEAKAKI0ICAAEF+IAV3cTYCiNCAgAAMAgsgAiAGRhogAiAENgIIIAQgAjYCDAwBCyADKAIYIQcCQAJAIAMoAgwiBiADRg0AIAMoAggiAkEAKAKY0ICAAEkaIAYgAjYCCCACIAY2AgwMAQsCQCADQRRqIgIoAgAiBA0AIANBEGoiAigCACIEDQBBACEGDAELA0AgAiEFIAQiBkEUaiICKAIAIgQNACAGQRBqIQIgBigCECIEDQALIAVBADYCAAsgB0UNAAJAAkAgAyADKAIcIgRBAnRBuNKAgABqIgIoAgBHDQAgAiAGNgIAIAYNAUEAQQAoAozQgIAAQX4gBHdxNgKM0ICAAAwCCyAHQRBBFCAHKAIQIANGG2ogBjYCACAGRQ0BCyAGIAc2AhgCQCADKAIQIgJFDQAgBiACNgIQIAIgBjYCGAsgAygCFCICRQ0AIAZBFGogAjYCACACIAY2AhgLIAEgAGogADYCACABIABBAXI2AgQgAUEAKAKc0ICAAEcNAUEAIAA2ApDQgIAADwsgAyACQX5xNgIEIAEgAGogADYCACABIABBAXI2AgQLAkAgAEH/AUsNACAAQXhxQbDQgIAAaiECAkACQEEAKAKI0ICAACIEQQEgAEEDdnQiAHENAEEAIAQgAHI2AojQgIAAIAIhAAwBCyACKAIIIQALIAAgATYCDCACIAE2AgggASACNgIMIAEgADYCCA8LQR8hAgJAIABB////B0sNACAAQQh2IgIgAkGA/j9qQRB2QQhxIgJ0IgQgBEGA4B9qQRB2QQRxIgR0IgYgBkGAgA9qQRB2QQJxIgZ0QQ92IAIgBHIgBnJrIgJBAXQgACACQRVqdkEBcXJBHGohAgsgASACNgIcIAFCADcCECACQQJ0QbjSgIAAaiEEAkACQEEAKAKM0ICAACIGQQEgAnQiA3ENACAEIAE2AgBBACAGIANyNgKM0ICAACABIAQ2AhggASABNgIIIAEgATYCDAwBCyAAQQBBGSACQQF2ayACQR9GG3QhAiAEKAIAIQYCQANAIAYiBCgCBEF4cSAARg0BIAJBHXYhBiACQQF0IQIgBCAGQQRxakEQaiIDKAIAIgYNAAsgAyABNgIAIAEgBDYCGCABIAE2AgwgASABNgIIDAELIAQoAggiACABNgIMIAQgATYCCCABQQA2AhggASAENgIMIAEgADYCCAtBAEEAKAKo0ICAAEF/aiIBQX8gARs2AqjQgIAACwsEAAAAC04AAkAgAA0APwBBEHQPCwJAIABB//8DcQ0AIABBf0wNAAJAIABBEHZAACIAQX9HDQBBAEEwNgL404CAAEF/DwsgAEEQdA8LEMqAgIAAAAvyAgIDfwF+AkAgAkUNACAAIAE6AAAgAiAAaiIDQX9qIAE6AAAgAkEDSQ0AIAAgAToAAiAAIAE6AAEgA0F9aiABOgAAIANBfmogAToAACACQQdJDQAgACABOgADIANBfGogAToAACACQQlJDQAgAEEAIABrQQNxIgRqIgMgAUH/AXFBgYKECGwiATYCACADIAIgBGtBfHEiBGoiAkF8aiABNgIAIARBCUkNACADIAE2AgggAyABNgIEIAJBeGogATYCACACQXRqIAE2AgAgBEEZSQ0AIAMgATYCGCADIAE2AhQgAyABNgIQIAMgATYCDCACQXBqIAE2AgAgAkFsaiABNgIAIAJBaGogATYCACACQWRqIAE2AgAgBCADQQRxQRhyIgVrIgJBIEkNACABrUKBgICAEH4hBiADIAVqIQEDQCABIAY3AxggASAGNwMQIAEgBjcDCCABIAY3AwAgAUEgaiEBIAJBYGoiAkEfSw0ACwsgAAsLjkgBAEGACAuGSAEAAAACAAAAAwAAAAAAAAAAAAAABAAAAAUAAAAAAAAAAAAAAAYAAAAHAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASW52YWxpZCBjaGFyIGluIHVybCBxdWVyeQBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX2JvZHkAQ29udGVudC1MZW5ndGggb3ZlcmZsb3cAQ2h1bmsgc2l6ZSBvdmVyZmxvdwBSZXNwb25zZSBvdmVyZmxvdwBJbnZhbGlkIG1ldGhvZCBmb3IgSFRUUC94LnggcmVxdWVzdABJbnZhbGlkIG1ldGhvZCBmb3IgUlRTUC94LnggcmVxdWVzdABFeHBlY3RlZCBTT1VSQ0UgbWV0aG9kIGZvciBJQ0UveC54IHJlcXVlc3QASW52YWxpZCBjaGFyIGluIHVybCBmcmFnbWVudCBzdGFydABFeHBlY3RlZCBkb3QAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9zdGF0dXMASW52YWxpZCByZXNwb25zZSBzdGF0dXMASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucwBVc2VyIGNhbGxiYWNrIGVycm9yAGBvbl9yZXNldGAgY2FsbGJhY2sgZXJyb3IAYG9uX2NodW5rX2hlYWRlcmAgY2FsbGJhY2sgZXJyb3IAYG9uX21lc3NhZ2VfYmVnaW5gIGNhbGxiYWNrIGVycm9yAGBvbl9jaHVua19leHRlbnNpb25fdmFsdWVgIGNhbGxiYWNrIGVycm9yAGBvbl9zdGF0dXNfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl92ZXJzaW9uX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fdXJsX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl9oZWFkZXJfdmFsdWVfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl9tZXNzYWdlX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fbWV0aG9kX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25faGVhZGVyX2ZpZWxkX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfZXh0ZW5zaW9uX25hbWVgIGNhbGxiYWNrIGVycm9yAFVuZXhwZWN0ZWQgY2hhciBpbiB1cmwgc2VydmVyAEludmFsaWQgaGVhZGVyIHZhbHVlIGNoYXIASW52YWxpZCBoZWFkZXIgZmllbGQgY2hhcgBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX3ZlcnNpb24ASW52YWxpZCBtaW5vciB2ZXJzaW9uAEludmFsaWQgbWFqb3IgdmVyc2lvbgBFeHBlY3RlZCBzcGFjZSBhZnRlciB2ZXJzaW9uAEV4cGVjdGVkIENSTEYgYWZ0ZXIgdmVyc2lvbgBJbnZhbGlkIEhUVFAgdmVyc2lvbgBJbnZhbGlkIGhlYWRlciB0b2tlbgBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX3VybABJbnZhbGlkIGNoYXJhY3RlcnMgaW4gdXJsAFVuZXhwZWN0ZWQgc3RhcnQgY2hhciBpbiB1cmwARG91YmxlIEAgaW4gdXJsAEVtcHR5IENvbnRlbnQtTGVuZ3RoAEludmFsaWQgY2hhcmFjdGVyIGluIENvbnRlbnQtTGVuZ3RoAER1cGxpY2F0ZSBDb250ZW50LUxlbmd0aABJbnZhbGlkIGNoYXIgaW4gdXJsIHBhdGgAQ29udGVudC1MZW5ndGggY2FuJ3QgYmUgcHJlc2VudCB3aXRoIFRyYW5zZmVyLUVuY29kaW5nAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIHNpemUAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9oZWFkZXJfdmFsdWUAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9jaHVua19leHRlbnNpb25fdmFsdWUASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucyB2YWx1ZQBNaXNzaW5nIGV4cGVjdGVkIExGIGFmdGVyIGhlYWRlciB2YWx1ZQBJbnZhbGlkIGBUcmFuc2Zlci1FbmNvZGluZ2AgaGVhZGVyIHZhbHVlAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMgcXVvdGUgdmFsdWUASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucyBxdW90ZWQgdmFsdWUAUGF1c2VkIGJ5IG9uX2hlYWRlcnNfY29tcGxldGUASW52YWxpZCBFT0Ygc3RhdGUAb25fcmVzZXQgcGF1c2UAb25fY2h1bmtfaGVhZGVyIHBhdXNlAG9uX21lc3NhZ2VfYmVnaW4gcGF1c2UAb25fY2h1bmtfZXh0ZW5zaW9uX3ZhbHVlIHBhdXNlAG9uX3N0YXR1c19jb21wbGV0ZSBwYXVzZQBvbl92ZXJzaW9uX2NvbXBsZXRlIHBhdXNlAG9uX3VybF9jb21wbGV0ZSBwYXVzZQBvbl9jaHVua19jb21wbGV0ZSBwYXVzZQBvbl9oZWFkZXJfdmFsdWVfY29tcGxldGUgcGF1c2UAb25fbWVzc2FnZV9jb21wbGV0ZSBwYXVzZQBvbl9tZXRob2RfY29tcGxldGUgcGF1c2UAb25faGVhZGVyX2ZpZWxkX2NvbXBsZXRlIHBhdXNlAG9uX2NodW5rX2V4dGVuc2lvbl9uYW1lIHBhdXNlAFVuZXhwZWN0ZWQgc3BhY2UgYWZ0ZXIgc3RhcnQgbGluZQBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX2NodW5rX2V4dGVuc2lvbl9uYW1lAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMgbmFtZQBQYXVzZSBvbiBDT05ORUNUL1VwZ3JhZGUAUGF1c2Ugb24gUFJJL1VwZ3JhZGUARXhwZWN0ZWQgSFRUUC8yIENvbm5lY3Rpb24gUHJlZmFjZQBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX21ldGhvZABFeHBlY3RlZCBzcGFjZSBhZnRlciBtZXRob2QAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9oZWFkZXJfZmllbGQAUGF1c2VkAEludmFsaWQgd29yZCBlbmNvdW50ZXJlZABJbnZhbGlkIG1ldGhvZCBlbmNvdW50ZXJlZABVbmV4cGVjdGVkIGNoYXIgaW4gdXJsIHNjaGVtYQBSZXF1ZXN0IGhhcyBpbnZhbGlkIGBUcmFuc2Zlci1FbmNvZGluZ2AAU1dJVENIX1BST1hZAFVTRV9QUk9YWQBNS0FDVElWSVRZAFVOUFJPQ0VTU0FCTEVfRU5USVRZAENPUFkATU9WRURfUEVSTUFORU5UTFkAVE9PX0VBUkxZAE5PVElGWQBGQUlMRURfREVQRU5ERU5DWQBCQURfR0FURVdBWQBQTEFZAFBVVABDSEVDS09VVABHQVRFV0FZX1RJTUVPVVQAUkVRVUVTVF9USU1FT1VUAE5FVFdPUktfQ09OTkVDVF9USU1FT1VUAENPTk5FQ1RJT05fVElNRU9VVABMT0dJTl9USU1FT1VUAE5FVFdPUktfUkVBRF9USU1FT1VUAFBPU1QATUlTRElSRUNURURfUkVRVUVTVABDTElFTlRfQ0xPU0VEX1JFUVVFU1QAQ0xJRU5UX0NMT1NFRF9MT0FEX0JBTEFOQ0VEX1JFUVVFU1QAQkFEX1JFUVVFU1QASFRUUF9SRVFVRVNUX1NFTlRfVE9fSFRUUFNfUE9SVABSRVBPUlQASU1fQV9URUFQT1QAUkVTRVRfQ09OVEVOVABOT19DT05URU5UAFBBUlRJQUxfQ09OVEVOVABIUEVfSU5WQUxJRF9DT05TVEFOVABIUEVfQ0JfUkVTRVQAR0VUAEhQRV9TVFJJQ1QAQ09ORkxJQ1QAVEVNUE9SQVJZX1JFRElSRUNUAFBFUk1BTkVOVF9SRURJUkVDVABDT05ORUNUAE1VTFRJX1NUQVRVUwBIUEVfSU5WQUxJRF9TVEFUVVMAVE9PX01BTllfUkVRVUVTVFMARUFSTFlfSElOVFMAVU5BVkFJTEFCTEVfRk9SX0xFR0FMX1JFQVNPTlMAT1BUSU9OUwBTV0lUQ0hJTkdfUFJPVE9DT0xTAFZBUklBTlRfQUxTT19ORUdPVElBVEVTAE1VTFRJUExFX0NIT0lDRVMASU5URVJOQUxfU0VSVkVSX0VSUk9SAFdFQl9TRVJWRVJfVU5LTk9XTl9FUlJPUgBSQUlMR1VOX0VSUk9SAElERU5USVRZX1BST1ZJREVSX0FVVEhFTlRJQ0FUSU9OX0VSUk9SAFNTTF9DRVJUSUZJQ0FURV9FUlJPUgBJTlZBTElEX1hfRk9SV0FSREVEX0ZPUgBTRVRfUEFSQU1FVEVSAEdFVF9QQVJBTUVURVIASFBFX1VTRVIAU0VFX09USEVSAEhQRV9DQl9DSFVOS19IRUFERVIATUtDQUxFTkRBUgBTRVRVUABXRUJfU0VSVkVSX0lTX0RPV04AVEVBUkRPV04ASFBFX0NMT1NFRF9DT05ORUNUSU9OAEhFVVJJU1RJQ19FWFBJUkFUSU9OAERJU0NPTk5FQ1RFRF9PUEVSQVRJT04ATk9OX0FVVEhPUklUQVRJVkVfSU5GT1JNQVRJT04ASFBFX0lOVkFMSURfVkVSU0lPTgBIUEVfQ0JfTUVTU0FHRV9CRUdJTgBTSVRFX0lTX0ZST1pFTgBIUEVfSU5WQUxJRF9IRUFERVJfVE9LRU4ASU5WQUxJRF9UT0tFTgBGT1JCSURERU4ARU5IQU5DRV9ZT1VSX0NBTE0ASFBFX0lOVkFMSURfVVJMAEJMT0NLRURfQllfUEFSRU5UQUxfQ09OVFJPTABNS0NPTABBQ0wASFBFX0lOVEVSTkFMAFJFUVVFU1RfSEVBREVSX0ZJRUxEU19UT09fTEFSR0VfVU5PRkZJQ0lBTABIUEVfT0sAVU5MSU5LAFVOTE9DSwBQUkkAUkVUUllfV0lUSABIUEVfSU5WQUxJRF9DT05URU5UX0xFTkdUSABIUEVfVU5FWFBFQ1RFRF9DT05URU5UX0xFTkdUSABGTFVTSABQUk9QUEFUQ0gATS1TRUFSQ0gAVVJJX1RPT19MT05HAFBST0NFU1NJTkcATUlTQ0VMTEFORU9VU19QRVJTSVNURU5UX1dBUk5JTkcATUlTQ0VMTEFORU9VU19XQVJOSU5HAEhQRV9JTlZBTElEX1RSQU5TRkVSX0VOQ09ESU5HAEV4cGVjdGVkIENSTEYASFBFX0lOVkFMSURfQ0hVTktfU0laRQBNT1ZFAENPTlRJTlVFAEhQRV9DQl9TVEFUVVNfQ09NUExFVEUASFBFX0NCX0hFQURFUlNfQ09NUExFVEUASFBFX0NCX1ZFUlNJT05fQ09NUExFVEUASFBFX0NCX1VSTF9DT01QTEVURQBIUEVfQ0JfQ0hVTktfQ09NUExFVEUASFBFX0NCX0hFQURFUl9WQUxVRV9DT01QTEVURQBIUEVfQ0JfQ0hVTktfRVhURU5TSU9OX1ZBTFVFX0NPTVBMRVRFAEhQRV9DQl9DSFVOS19FWFRFTlNJT05fTkFNRV9DT01QTEVURQBIUEVfQ0JfTUVTU0FHRV9DT01QTEVURQBIUEVfQ0JfTUVUSE9EX0NPTVBMRVRFAEhQRV9DQl9IRUFERVJfRklFTERfQ09NUExFVEUAREVMRVRFAEhQRV9JTlZBTElEX0VPRl9TVEFURQBJTlZBTElEX1NTTF9DRVJUSUZJQ0FURQBQQVVTRQBOT19SRVNQT05TRQBVTlNVUFBPUlRFRF9NRURJQV9UWVBFAEdPTkUATk9UX0FDQ0VQVEFCTEUAU0VSVklDRV9VTkFWQUlMQUJMRQBSQU5HRV9OT1RfU0FUSVNGSUFCTEUAT1JJR0lOX0lTX1VOUkVBQ0hBQkxFAFJFU1BPTlNFX0lTX1NUQUxFAFBVUkdFAE1FUkdFAFJFUVVFU1RfSEVBREVSX0ZJRUxEU19UT09fTEFSR0UAUkVRVUVTVF9IRUFERVJfVE9PX0xBUkdFAFBBWUxPQURfVE9PX0xBUkdFAElOU1VGRklDSUVOVF9TVE9SQUdFAEhQRV9QQVVTRURfVVBHUkFERQBIUEVfUEFVU0VEX0gyX1VQR1JBREUAU09VUkNFAEFOTk9VTkNFAFRSQUNFAEhQRV9VTkVYUEVDVEVEX1NQQUNFAERFU0NSSUJFAFVOU1VCU0NSSUJFAFJFQ09SRABIUEVfSU5WQUxJRF9NRVRIT0QATk9UX0ZPVU5EAFBST1BGSU5EAFVOQklORABSRUJJTkQAVU5BVVRIT1JJWkVEAE1FVEhPRF9OT1RfQUxMT1dFRABIVFRQX1ZFUlNJT05fTk9UX1NVUFBPUlRFRABBTFJFQURZX1JFUE9SVEVEAEFDQ0VQVEVEAE5PVF9JTVBMRU1FTlRFRABMT09QX0RFVEVDVEVEAEhQRV9DUl9FWFBFQ1RFRABIUEVfTEZfRVhQRUNURUQAQ1JFQVRFRABJTV9VU0VEAEhQRV9QQVVTRUQAVElNRU9VVF9PQ0NVUkVEAFBBWU1FTlRfUkVRVUlSRUQAUFJFQ09ORElUSU9OX1JFUVVJUkVEAFBST1hZX0FVVEhFTlRJQ0FUSU9OX1JFUVVJUkVEAE5FVFdPUktfQVVUSEVOVElDQVRJT05fUkVRVUlSRUQATEVOR1RIX1JFUVVJUkVEAFNTTF9DRVJUSUZJQ0FURV9SRVFVSVJFRABVUEdSQURFX1JFUVVJUkVEAFBBR0VfRVhQSVJFRABQUkVDT05ESVRJT05fRkFJTEVEAEVYUEVDVEFUSU9OX0ZBSUxFRABSRVZBTElEQVRJT05fRkFJTEVEAFNTTF9IQU5EU0hBS0VfRkFJTEVEAExPQ0tFRABUUkFOU0ZPUk1BVElPTl9BUFBMSUVEAE5PVF9NT0RJRklFRABOT1RfRVhURU5ERUQAQkFORFdJRFRIX0xJTUlUX0VYQ0VFREVEAFNJVEVfSVNfT1ZFUkxPQURFRABIRUFEAEV4cGVjdGVkIEhUVFAvAABeEwAAJhMAADAQAADwFwAAnRMAABUSAAA5FwAA8BIAAAoQAAB1EgAArRIAAIITAABPFAAAfxAAAKAVAAAjFAAAiRIAAIsUAABNFQAA1BEAAM8UAAAQGAAAyRYAANwWAADBEQAA4BcAALsUAAB0FAAAfBUAAOUUAAAIFwAAHxAAAGUVAACjFAAAKBUAAAIVAACZFQAALBAAAIsZAABPDwAA1A4AAGoQAADOEAAAAhcAAIkOAABuEwAAHBMAAGYUAABWFwAAwRMAAM0TAABsEwAAaBcAAGYXAABfFwAAIhMAAM4PAABpDgAA2A4AAGMWAADLEwAAqg4AACgXAAAmFwAAxRMAAF0WAADoEQAAZxMAAGUTAADyFgAAcxMAAB0XAAD5FgAA8xEAAM8OAADOFQAADBIAALMRAAClEQAAYRAAADIXAAC7EwAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAgEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAgMCAgICAgAAAgIAAgIAAgICAgICAgICAgAEAAAAAAACAgICAgICAgICAgICAgICAgICAgICAgICAgAAAAICAgICAgICAgICAgICAgICAgICAgICAgICAgICAAIAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIAAgICAgIAAAICAAICAAICAgICAgICAgIAAwAEAAAAAgICAgICAgICAgICAgICAgICAgICAgICAgIAAAACAgICAgICAgICAgICAgICAgICAgICAgICAgICAgACAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABsb3NlZWVwLWFsaXZlAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAgEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQFjaHVua2VkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQABAQEBAQAAAQEAAQEAAQEBAQEBAQEBAQAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGVjdGlvbmVudC1sZW5ndGhvbnJveHktY29ubmVjdGlvbgAAAAAAAAAAAAAAAAAAAHJhbnNmZXItZW5jb2RpbmdwZ3JhZGUNCg0KDQpTTQ0KDQpUVFAvQ0UvVFNQLwAAAAAAAAAAAAAAAAECAAEDAAAAAAAAAAAAAAAAAAAAAAAABAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAABAgABAwAAAAAAAAAAAAAAAAAAAAAAAAQBAQUBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAQAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAABAAACAAAAAAAAAAAAAAAAAAAAAAAAAwQAAAQEBAQEBAQEBAQEBQQEBAQEBAQEBAQEBAAEAAYHBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQABAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAQAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAAAAAAAAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAEAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAgAAAAACAAAAAAAAAAAAAAAAAAAAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwAAAAAAAAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE5PVU5DRUVDS09VVE5FQ1RFVEVDUklCRUxVU0hFVEVBRFNFQVJDSFJHRUNUSVZJVFlMRU5EQVJWRU9USUZZUFRJT05TQ0hTRUFZU1RBVENIR0VPUkRJUkVDVE9SVFJDSFBBUkFNRVRFUlVSQ0VCU0NSSUJFQVJET1dOQUNFSU5ETktDS1VCU0NSSUJFSFRUUC9BRFRQLw==' + + +/***/ }), + +/***/ 3537: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.enumToMap = void 0; +function enumToMap(obj) { + const res = {}; + Object.keys(obj).forEach((key) => { + const value = obj[key]; + if (typeof value === 'number') { + res[key] = value; + } + }); + return res; +} +exports.enumToMap = enumToMap; +//# sourceMappingURL=utils.js.map + +/***/ }), + +/***/ 6070: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { kClients } = __nccwpck_require__(9440) +const Agent = __nccwpck_require__(8596) +const { + kAgent, + kMockAgentSet, + kMockAgentGet, + kDispatches, + kIsMockActive, + kNetConnect, + kGetNetConnect, + kOptions, + kFactory +} = __nccwpck_require__(5873) +const MockClient = __nccwpck_require__(5846) +const MockPool = __nccwpck_require__(5020) +const { matchValue, buildMockOptions } = __nccwpck_require__(7458) +const { InvalidArgumentError, UndiciError } = __nccwpck_require__(721) +const Dispatcher = __nccwpck_require__(6504) +const Pluralizer = __nccwpck_require__(4226) +const PendingInterceptorsFormatter = __nccwpck_require__(9452) + +class FakeWeakRef { + constructor (value) { + this.value = value + } + + deref () { + return this.value + } +} + +class MockAgent extends Dispatcher { + constructor (opts) { + super(opts) + + this[kNetConnect] = true + this[kIsMockActive] = true + + // Instantiate Agent and encapsulate + if ((opts && opts.agent && typeof opts.agent.dispatch !== 'function')) { + throw new InvalidArgumentError('Argument opts.agent must implement Agent') + } + const agent = opts && opts.agent ? opts.agent : new Agent(opts) + this[kAgent] = agent + + this[kClients] = agent[kClients] + this[kOptions] = buildMockOptions(opts) + } + + get (origin) { + let dispatcher = this[kMockAgentGet](origin) + + if (!dispatcher) { + dispatcher = this[kFactory](origin) + this[kMockAgentSet](origin, dispatcher) + } + return dispatcher + } + + dispatch (opts, handler) { + // Call MockAgent.get to perform additional setup before dispatching as normal + this.get(opts.origin) + return this[kAgent].dispatch(opts, handler) + } + + async close () { + await this[kAgent].close() + this[kClients].clear() + } + + deactivate () { + this[kIsMockActive] = false + } + + activate () { + this[kIsMockActive] = true + } + + enableNetConnect (matcher) { + if (typeof matcher === 'string' || typeof matcher === 'function' || matcher instanceof RegExp) { + if (Array.isArray(this[kNetConnect])) { + this[kNetConnect].push(matcher) + } else { + this[kNetConnect] = [matcher] + } + } else if (typeof matcher === 'undefined') { + this[kNetConnect] = true + } else { + throw new InvalidArgumentError('Unsupported matcher. Must be one of String|Function|RegExp.') + } + } + + disableNetConnect () { + this[kNetConnect] = false + } + + // This is required to bypass issues caused by using global symbols - see: + // https://github.com/nodejs/undici/issues/1447 + get isMockActive () { + return this[kIsMockActive] + } + + [kMockAgentSet] (origin, dispatcher) { + this[kClients].set(origin, new FakeWeakRef(dispatcher)) + } + + [kFactory] (origin) { + const mockOptions = Object.assign({ agent: this }, this[kOptions]) + return this[kOptions] && this[kOptions].connections === 1 + ? new MockClient(origin, mockOptions) + : new MockPool(origin, mockOptions) + } + + [kMockAgentGet] (origin) { + // First check if we can immediately find it + const ref = this[kClients].get(origin) + if (ref) { + return ref.deref() + } + + // If the origin is not a string create a dummy parent pool and return to user + if (typeof origin !== 'string') { + const dispatcher = this[kFactory]('http://localhost:9999') + this[kMockAgentSet](origin, dispatcher) + return dispatcher + } + + // If we match, create a pool and assign the same dispatches + for (const [keyMatcher, nonExplicitRef] of Array.from(this[kClients])) { + const nonExplicitDispatcher = nonExplicitRef.deref() + if (nonExplicitDispatcher && typeof keyMatcher !== 'string' && matchValue(keyMatcher, origin)) { + const dispatcher = this[kFactory](origin) + this[kMockAgentSet](origin, dispatcher) + dispatcher[kDispatches] = nonExplicitDispatcher[kDispatches] + return dispatcher + } + } + } + + [kGetNetConnect] () { + return this[kNetConnect] + } + + pendingInterceptors () { + const mockAgentClients = this[kClients] + + return Array.from(mockAgentClients.entries()) + .flatMap(([origin, scope]) => scope.deref()[kDispatches].map(dispatch => ({ ...dispatch, origin }))) + .filter(({ pending }) => pending) + } + + assertNoPendingInterceptors ({ pendingInterceptorsFormatter = new PendingInterceptorsFormatter() } = {}) { + const pending = this.pendingInterceptors() + + if (pending.length === 0) { + return + } + + const pluralizer = new Pluralizer('interceptor', 'interceptors').pluralize(pending.length) + + throw new UndiciError(` +${pluralizer.count} ${pluralizer.noun} ${pluralizer.is} pending: + +${pendingInterceptorsFormatter.format(pending)} +`.trim()) + } +} + +module.exports = MockAgent + + +/***/ }), + +/***/ 5846: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { promisify } = __nccwpck_require__(3837) +const Client = __nccwpck_require__(1180) +const { buildMockDispatch } = __nccwpck_require__(7458) +const { + kDispatches, + kMockAgent, + kClose, + kOriginalClose, + kOrigin, + kOriginalDispatch, + kConnected +} = __nccwpck_require__(5873) +const { MockInterceptor } = __nccwpck_require__(4127) +const Symbols = __nccwpck_require__(9440) +const { InvalidArgumentError } = __nccwpck_require__(721) + +/** + * MockClient provides an API that extends the Client to influence the mockDispatches. + */ +class MockClient extends Client { + constructor (origin, opts) { + super(origin, opts) + + if (!opts || !opts.agent || typeof opts.agent.dispatch !== 'function') { + throw new InvalidArgumentError('Argument opts.agent must implement Agent') + } + + this[kMockAgent] = opts.agent + this[kOrigin] = origin + this[kDispatches] = [] + this[kConnected] = 1 + this[kOriginalDispatch] = this.dispatch + this[kOriginalClose] = this.close.bind(this) + + this.dispatch = buildMockDispatch.call(this) + this.close = this[kClose] + } + + get [Symbols.kConnected] () { + return this[kConnected] + } + + /** + * Sets up the base interceptor for mocking replies from undici. + */ + intercept (opts) { + return new MockInterceptor(opts, this[kDispatches]) + } + + async [kClose] () { + await promisify(this[kOriginalClose])() + this[kConnected] = 0 + this[kMockAgent][Symbols.kClients].delete(this[kOrigin]) + } +} + +module.exports = MockClient + + +/***/ }), + +/***/ 64: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { UndiciError } = __nccwpck_require__(721) + +class MockNotMatchedError extends UndiciError { + constructor (message) { + super(message) + Error.captureStackTrace(this, MockNotMatchedError) + this.name = 'MockNotMatchedError' + this.message = message || 'The request does not match any registered mock dispatches' + this.code = 'UND_MOCK_ERR_MOCK_NOT_MATCHED' + } +} + +module.exports = { + MockNotMatchedError +} + + +/***/ }), + +/***/ 4127: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { getResponseData, buildKey, addMockDispatch } = __nccwpck_require__(7458) +const { + kDispatches, + kDispatchKey, + kDefaultHeaders, + kDefaultTrailers, + kContentLength, + kMockDispatch +} = __nccwpck_require__(5873) +const { InvalidArgumentError } = __nccwpck_require__(721) +const { buildURL } = __nccwpck_require__(9522) + +/** + * Defines the scope API for an interceptor reply + */ +class MockScope { + constructor (mockDispatch) { + this[kMockDispatch] = mockDispatch + } + + /** + * Delay a reply by a set amount in ms. + */ + delay (waitInMs) { + if (typeof waitInMs !== 'number' || !Number.isInteger(waitInMs) || waitInMs <= 0) { + throw new InvalidArgumentError('waitInMs must be a valid integer > 0') + } + + this[kMockDispatch].delay = waitInMs + return this + } + + /** + * For a defined reply, never mark as consumed. + */ + persist () { + this[kMockDispatch].persist = true + return this + } + + /** + * Allow one to define a reply for a set amount of matching requests. + */ + times (repeatTimes) { + if (typeof repeatTimes !== 'number' || !Number.isInteger(repeatTimes) || repeatTimes <= 0) { + throw new InvalidArgumentError('repeatTimes must be a valid integer > 0') + } + + this[kMockDispatch].times = repeatTimes + return this + } +} + +/** + * Defines an interceptor for a Mock + */ +class MockInterceptor { + constructor (opts, mockDispatches) { + if (typeof opts !== 'object') { + throw new InvalidArgumentError('opts must be an object') + } + if (typeof opts.path === 'undefined') { + throw new InvalidArgumentError('opts.path must be defined') + } + if (typeof opts.method === 'undefined') { + opts.method = 'GET' + } + // See https://github.com/nodejs/undici/issues/1245 + // As per RFC 3986, clients are not supposed to send URI + // fragments to servers when they retrieve a document, + if (typeof opts.path === 'string') { + if (opts.query) { + opts.path = buildURL(opts.path, opts.query) + } else { + // Matches https://github.com/nodejs/undici/blob/main/lib/fetch/index.js#L1811 + const parsedURL = new URL(opts.path, 'data://') + opts.path = parsedURL.pathname + parsedURL.search + } + } + if (typeof opts.method === 'string') { + opts.method = opts.method.toUpperCase() + } + + this[kDispatchKey] = buildKey(opts) + this[kDispatches] = mockDispatches + this[kDefaultHeaders] = {} + this[kDefaultTrailers] = {} + this[kContentLength] = false + } + + createMockScopeDispatchData (statusCode, data, responseOptions = {}) { + const responseData = getResponseData(data) + const contentLength = this[kContentLength] ? { 'content-length': responseData.length } : {} + const headers = { ...this[kDefaultHeaders], ...contentLength, ...responseOptions.headers } + const trailers = { ...this[kDefaultTrailers], ...responseOptions.trailers } + + return { statusCode, data, headers, trailers } + } + + validateReplyParameters (statusCode, data, responseOptions) { + if (typeof statusCode === 'undefined') { + throw new InvalidArgumentError('statusCode must be defined') + } + if (typeof data === 'undefined') { + throw new InvalidArgumentError('data must be defined') + } + if (typeof responseOptions !== 'object') { + throw new InvalidArgumentError('responseOptions must be an object') + } + } + + /** + * Mock an undici request with a defined reply. + */ + reply (replyData) { + // Values of reply aren't available right now as they + // can only be available when the reply callback is invoked. + if (typeof replyData === 'function') { + // We'll first wrap the provided callback in another function, + // this function will properly resolve the data from the callback + // when invoked. + const wrappedDefaultsCallback = (opts) => { + // Our reply options callback contains the parameter for statusCode, data and options. + const resolvedData = replyData(opts) + + // Check if it is in the right format + if (typeof resolvedData !== 'object') { + throw new InvalidArgumentError('reply options callback must return an object') + } + + const { statusCode, data = '', responseOptions = {} } = resolvedData + this.validateReplyParameters(statusCode, data, responseOptions) + // Since the values can be obtained immediately we return them + // from this higher order function that will be resolved later. + return { + ...this.createMockScopeDispatchData(statusCode, data, responseOptions) + } + } + + // Add usual dispatch data, but this time set the data parameter to function that will eventually provide data. + const newMockDispatch = addMockDispatch(this[kDispatches], this[kDispatchKey], wrappedDefaultsCallback) + return new MockScope(newMockDispatch) + } + + // We can have either one or three parameters, if we get here, + // we should have 1-3 parameters. So we spread the arguments of + // this function to obtain the parameters, since replyData will always + // just be the statusCode. + const [statusCode, data = '', responseOptions = {}] = [...arguments] + this.validateReplyParameters(statusCode, data, responseOptions) + + // Send in-already provided data like usual + const dispatchData = this.createMockScopeDispatchData(statusCode, data, responseOptions) + const newMockDispatch = addMockDispatch(this[kDispatches], this[kDispatchKey], dispatchData) + return new MockScope(newMockDispatch) + } + + /** + * Mock an undici request with a defined error. + */ + replyWithError (error) { + if (typeof error === 'undefined') { + throw new InvalidArgumentError('error must be defined') + } + + const newMockDispatch = addMockDispatch(this[kDispatches], this[kDispatchKey], { error }) + return new MockScope(newMockDispatch) + } + + /** + * Set default reply headers on the interceptor for subsequent replies + */ + defaultReplyHeaders (headers) { + if (typeof headers === 'undefined') { + throw new InvalidArgumentError('headers must be defined') + } + + this[kDefaultHeaders] = headers + return this + } + + /** + * Set default reply trailers on the interceptor for subsequent replies + */ + defaultReplyTrailers (trailers) { + if (typeof trailers === 'undefined') { + throw new InvalidArgumentError('trailers must be defined') + } + + this[kDefaultTrailers] = trailers + return this + } + + /** + * Set reply content length header for replies on the interceptor + */ + replyContentLength () { + this[kContentLength] = true + return this + } +} + +module.exports.MockInterceptor = MockInterceptor +module.exports.MockScope = MockScope + + +/***/ }), + +/***/ 5020: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { promisify } = __nccwpck_require__(3837) +const Pool = __nccwpck_require__(2395) +const { buildMockDispatch } = __nccwpck_require__(7458) +const { + kDispatches, + kMockAgent, + kClose, + kOriginalClose, + kOrigin, + kOriginalDispatch, + kConnected +} = __nccwpck_require__(5873) +const { MockInterceptor } = __nccwpck_require__(4127) +const Symbols = __nccwpck_require__(9440) +const { InvalidArgumentError } = __nccwpck_require__(721) + +/** + * MockPool provides an API that extends the Pool to influence the mockDispatches. + */ +class MockPool extends Pool { + constructor (origin, opts) { + super(origin, opts) + + if (!opts || !opts.agent || typeof opts.agent.dispatch !== 'function') { + throw new InvalidArgumentError('Argument opts.agent must implement Agent') + } + + this[kMockAgent] = opts.agent + this[kOrigin] = origin + this[kDispatches] = [] + this[kConnected] = 1 + this[kOriginalDispatch] = this.dispatch + this[kOriginalClose] = this.close.bind(this) + + this.dispatch = buildMockDispatch.call(this) + this.close = this[kClose] + } + + get [Symbols.kConnected] () { + return this[kConnected] + } + + /** + * Sets up the base interceptor for mocking replies from undici. + */ + intercept (opts) { + return new MockInterceptor(opts, this[kDispatches]) + } + + async [kClose] () { + await promisify(this[kOriginalClose])() + this[kConnected] = 0 + this[kMockAgent][Symbols.kClients].delete(this[kOrigin]) + } +} + +module.exports = MockPool + + +/***/ }), + +/***/ 5873: +/***/ ((module) => { + +"use strict"; + + +module.exports = { + kAgent: Symbol('agent'), + kOptions: Symbol('options'), + kFactory: Symbol('factory'), + kDispatches: Symbol('dispatches'), + kDispatchKey: Symbol('dispatch key'), + kDefaultHeaders: Symbol('default headers'), + kDefaultTrailers: Symbol('default trailers'), + kContentLength: Symbol('content length'), + kMockAgent: Symbol('mock agent'), + kMockAgentSet: Symbol('mock agent set'), + kMockAgentGet: Symbol('mock agent get'), + kMockDispatch: Symbol('mock dispatch'), + kClose: Symbol('close'), + kOriginalClose: Symbol('original agent close'), + kOrigin: Symbol('origin'), + kIsMockActive: Symbol('is mock active'), + kNetConnect: Symbol('net connect'), + kGetNetConnect: Symbol('get net connect'), + kConnected: Symbol('connected') +} + + +/***/ }), + +/***/ 7458: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { MockNotMatchedError } = __nccwpck_require__(64) +const { + kDispatches, + kMockAgent, + kOriginalDispatch, + kOrigin, + kGetNetConnect +} = __nccwpck_require__(5873) +const { buildURL, nop } = __nccwpck_require__(9522) +const { STATUS_CODES } = __nccwpck_require__(3685) +const { + types: { + isPromise + } +} = __nccwpck_require__(3837) + +function matchValue (match, value) { + if (typeof match === 'string') { + return match === value + } + if (match instanceof RegExp) { + return match.test(value) + } + if (typeof match === 'function') { + return match(value) === true + } + return false +} + +function lowerCaseEntries (headers) { + return Object.fromEntries( + Object.entries(headers).map(([headerName, headerValue]) => { + return [headerName.toLocaleLowerCase(), headerValue] + }) + ) +} + +/** + * @param {import('../../index').Headers|string[]|Record} headers + * @param {string} key + */ +function getHeaderByName (headers, key) { + if (Array.isArray(headers)) { + for (let i = 0; i < headers.length; i += 2) { + if (headers[i].toLocaleLowerCase() === key.toLocaleLowerCase()) { + return headers[i + 1] + } + } + + return undefined + } else if (typeof headers.get === 'function') { + return headers.get(key) + } else { + return lowerCaseEntries(headers)[key.toLocaleLowerCase()] + } +} + +/** @param {string[]} headers */ +function buildHeadersFromArray (headers) { // fetch HeadersList + const clone = headers.slice() + const entries = [] + for (let index = 0; index < clone.length; index += 2) { + entries.push([clone[index], clone[index + 1]]) + } + return Object.fromEntries(entries) +} + +function matchHeaders (mockDispatch, headers) { + if (typeof mockDispatch.headers === 'function') { + if (Array.isArray(headers)) { // fetch HeadersList + headers = buildHeadersFromArray(headers) + } + return mockDispatch.headers(headers ? lowerCaseEntries(headers) : {}) + } + if (typeof mockDispatch.headers === 'undefined') { + return true + } + if (typeof headers !== 'object' || typeof mockDispatch.headers !== 'object') { + return false + } + + for (const [matchHeaderName, matchHeaderValue] of Object.entries(mockDispatch.headers)) { + const headerValue = getHeaderByName(headers, matchHeaderName) + + if (!matchValue(matchHeaderValue, headerValue)) { + return false + } + } + return true +} + +function safeUrl (path) { + if (typeof path !== 'string') { + return path + } + + const pathSegments = path.split('?') + + if (pathSegments.length !== 2) { + return path + } + + const qp = new URLSearchParams(pathSegments.pop()) + qp.sort() + return [...pathSegments, qp.toString()].join('?') +} + +function matchKey (mockDispatch, { path, method, body, headers }) { + const pathMatch = matchValue(mockDispatch.path, path) + const methodMatch = matchValue(mockDispatch.method, method) + const bodyMatch = typeof mockDispatch.body !== 'undefined' ? matchValue(mockDispatch.body, body) : true + const headersMatch = matchHeaders(mockDispatch, headers) + return pathMatch && methodMatch && bodyMatch && headersMatch +} + +function getResponseData (data) { + if (Buffer.isBuffer(data)) { + return data + } else if (typeof data === 'object') { + return JSON.stringify(data) + } else { + return data.toString() + } +} + +function getMockDispatch (mockDispatches, key) { + const basePath = key.query ? buildURL(key.path, key.query) : key.path + const resolvedPath = typeof basePath === 'string' ? safeUrl(basePath) : basePath + + // Match path + let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path }) => matchValue(safeUrl(path), resolvedPath)) + if (matchedMockDispatches.length === 0) { + throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`) + } + + // Match method + matchedMockDispatches = matchedMockDispatches.filter(({ method }) => matchValue(method, key.method)) + if (matchedMockDispatches.length === 0) { + throw new MockNotMatchedError(`Mock dispatch not matched for method '${key.method}'`) + } + + // Match body + matchedMockDispatches = matchedMockDispatches.filter(({ body }) => typeof body !== 'undefined' ? matchValue(body, key.body) : true) + if (matchedMockDispatches.length === 0) { + throw new MockNotMatchedError(`Mock dispatch not matched for body '${key.body}'`) + } + + // Match headers + matchedMockDispatches = matchedMockDispatches.filter((mockDispatch) => matchHeaders(mockDispatch, key.headers)) + if (matchedMockDispatches.length === 0) { + throw new MockNotMatchedError(`Mock dispatch not matched for headers '${typeof key.headers === 'object' ? JSON.stringify(key.headers) : key.headers}'`) + } + + return matchedMockDispatches[0] +} + +function addMockDispatch (mockDispatches, key, data) { + const baseData = { timesInvoked: 0, times: 1, persist: false, consumed: false } + const replyData = typeof data === 'function' ? { callback: data } : { ...data } + const newMockDispatch = { ...baseData, ...key, pending: true, data: { error: null, ...replyData } } + mockDispatches.push(newMockDispatch) + return newMockDispatch +} + +function deleteMockDispatch (mockDispatches, key) { + const index = mockDispatches.findIndex(dispatch => { + if (!dispatch.consumed) { + return false + } + return matchKey(dispatch, key) + }) + if (index !== -1) { + mockDispatches.splice(index, 1) + } +} + +function buildKey (opts) { + const { path, method, body, headers, query } = opts + return { + path, + method, + body, + headers, + query + } +} + +function generateKeyValues (data) { + return Object.entries(data).reduce((keyValuePairs, [key, value]) => [ + ...keyValuePairs, + Buffer.from(`${key}`), + Array.isArray(value) ? value.map(x => Buffer.from(`${x}`)) : Buffer.from(`${value}`) + ], []) +} + +/** + * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Status + * @param {number} statusCode + */ +function getStatusText (statusCode) { + return STATUS_CODES[statusCode] || 'unknown' +} + +async function getResponse (body) { + const buffers = [] + for await (const data of body) { + buffers.push(data) + } + return Buffer.concat(buffers).toString('utf8') +} + +/** + * Mock dispatch function used to simulate undici dispatches + */ +function mockDispatch (opts, handler) { + // Get mock dispatch from built key + const key = buildKey(opts) + const mockDispatch = getMockDispatch(this[kDispatches], key) + + mockDispatch.timesInvoked++ + + // Here's where we resolve a callback if a callback is present for the dispatch data. + if (mockDispatch.data.callback) { + mockDispatch.data = { ...mockDispatch.data, ...mockDispatch.data.callback(opts) } + } + + // Parse mockDispatch data + const { data: { statusCode, data, headers, trailers, error }, delay, persist } = mockDispatch + const { timesInvoked, times } = mockDispatch + + // If it's used up and not persistent, mark as consumed + mockDispatch.consumed = !persist && timesInvoked >= times + mockDispatch.pending = timesInvoked < times + + // If specified, trigger dispatch error + if (error !== null) { + deleteMockDispatch(this[kDispatches], key) + handler.onError(error) + return true + } + + // Handle the request with a delay if necessary + if (typeof delay === 'number' && delay > 0) { + setTimeout(() => { + handleReply(this[kDispatches]) + }, delay) + } else { + handleReply(this[kDispatches]) + } + + function handleReply (mockDispatches, _data = data) { + // fetch's HeadersList is a 1D string array + const optsHeaders = Array.isArray(opts.headers) + ? buildHeadersFromArray(opts.headers) + : opts.headers + const body = typeof _data === 'function' + ? _data({ ...opts, headers: optsHeaders }) + : _data + + // util.types.isPromise is likely needed for jest. + if (isPromise(body)) { + // If handleReply is asynchronous, throwing an error + // in the callback will reject the promise, rather than + // synchronously throw the error, which breaks some tests. + // Rather, we wait for the callback to resolve if it is a + // promise, and then re-run handleReply with the new body. + body.then((newData) => handleReply(mockDispatches, newData)) + return + } + + const responseData = getResponseData(body) + const responseHeaders = generateKeyValues(headers) + const responseTrailers = generateKeyValues(trailers) + + handler.abort = nop + handler.onHeaders(statusCode, responseHeaders, resume, getStatusText(statusCode)) + handler.onData(Buffer.from(responseData)) + handler.onComplete(responseTrailers) + deleteMockDispatch(mockDispatches, key) + } + + function resume () {} + + return true +} + +function buildMockDispatch () { + const agent = this[kMockAgent] + const origin = this[kOrigin] + const originalDispatch = this[kOriginalDispatch] + + return function dispatch (opts, handler) { + if (agent.isMockActive) { + try { + mockDispatch.call(this, opts, handler) + } catch (error) { + if (error instanceof MockNotMatchedError) { + const netConnect = agent[kGetNetConnect]() + if (netConnect === false) { + throw new MockNotMatchedError(`${error.message}: subsequent request to origin ${origin} was not allowed (net.connect disabled)`) + } + if (checkNetConnect(netConnect, origin)) { + originalDispatch.call(this, opts, handler) + } else { + throw new MockNotMatchedError(`${error.message}: subsequent request to origin ${origin} was not allowed (net.connect is not enabled for this origin)`) + } + } else { + throw error + } + } + } else { + originalDispatch.call(this, opts, handler) + } + } +} + +function checkNetConnect (netConnect, origin) { + const url = new URL(origin) + if (netConnect === true) { + return true + } else if (Array.isArray(netConnect) && netConnect.some((matcher) => matchValue(matcher, url.host))) { + return true + } + return false +} + +function buildMockOptions (opts) { + if (opts) { + const { agent, ...mockOptions } = opts + return mockOptions + } +} + +module.exports = { + getResponseData, + getMockDispatch, + addMockDispatch, + deleteMockDispatch, + buildKey, + generateKeyValues, + matchValue, + getResponse, + getStatusText, + mockDispatch, + buildMockDispatch, + checkNetConnect, + buildMockOptions, + getHeaderByName +} + + +/***/ }), + +/***/ 9452: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { Transform } = __nccwpck_require__(2781) +const { Console } = __nccwpck_require__(6206) + +/** + * Gets the output of `console.table(…)` as a string. + */ +module.exports = class PendingInterceptorsFormatter { + constructor ({ disableColors } = {}) { + this.transform = new Transform({ + transform (chunk, _enc, cb) { + cb(null, chunk) + } + }) + + this.logger = new Console({ + stdout: this.transform, + inspectOptions: { + colors: !disableColors && !process.env.CI + } + }) + } + + format (pendingInterceptors) { + const withPrettyHeaders = pendingInterceptors.map( + ({ method, path, data: { statusCode }, persist, times, timesInvoked, origin }) => ({ + Method: method, + Origin: origin, + Path: path, + 'Status code': statusCode, + Persistent: persist ? '✅' : '❌', + Invocations: timesInvoked, + Remaining: persist ? Infinity : times - timesInvoked + })) + + this.logger.table(withPrettyHeaders) + return this.transform.read().toString() + } +} + + +/***/ }), + +/***/ 4226: +/***/ ((module) => { + +"use strict"; + + +const singulars = { + pronoun: 'it', + is: 'is', + was: 'was', + this: 'this' +} + +const plurals = { + pronoun: 'they', + is: 'are', + was: 'were', + this: 'these' +} + +module.exports = class Pluralizer { + constructor (singular, plural) { + this.singular = singular + this.plural = plural + } + + pluralize (count) { + const one = count === 1 + const keys = one ? singulars : plurals + const noun = one ? this.singular : this.plural + return { ...keys, count, noun } + } +} + + +/***/ }), + +/***/ 6937: +/***/ ((module) => { + +"use strict"; +/* eslint-disable */ + + + +// Extracted from node/lib/internal/fixed_queue.js + +// Currently optimal queue size, tested on V8 6.0 - 6.6. Must be power of two. +const kSize = 2048; +const kMask = kSize - 1; + +// The FixedQueue is implemented as a singly-linked list of fixed-size +// circular buffers. It looks something like this: +// +// head tail +// | | +// v v +// +-----------+ <-----\ +-----------+ <------\ +-----------+ +// | [null] | \----- | next | \------- | next | +// +-----------+ +-----------+ +-----------+ +// | item | <-- bottom | item | <-- bottom | [empty] | +// | item | | item | | [empty] | +// | item | | item | | [empty] | +// | item | | item | | [empty] | +// | item | | item | bottom --> | item | +// | item | | item | | item | +// | ... | | ... | | ... | +// | item | | item | | item | +// | item | | item | | item | +// | [empty] | <-- top | item | | item | +// | [empty] | | item | | item | +// | [empty] | | [empty] | <-- top top --> | [empty] | +// +-----------+ +-----------+ +-----------+ +// +// Or, if there is only one circular buffer, it looks something +// like either of these: +// +// head tail head tail +// | | | | +// v v v v +// +-----------+ +-----------+ +// | [null] | | [null] | +// +-----------+ +-----------+ +// | [empty] | | item | +// | [empty] | | item | +// | item | <-- bottom top --> | [empty] | +// | item | | [empty] | +// | [empty] | <-- top bottom --> | item | +// | [empty] | | item | +// +-----------+ +-----------+ +// +// Adding a value means moving `top` forward by one, removing means +// moving `bottom` forward by one. After reaching the end, the queue +// wraps around. +// +// When `top === bottom` the current queue is empty and when +// `top + 1 === bottom` it's full. This wastes a single space of storage +// but allows much quicker checks. + +class FixedCircularBuffer { + constructor() { + this.bottom = 0; + this.top = 0; + this.list = new Array(kSize); + this.next = null; + } + + isEmpty() { + return this.top === this.bottom; + } + + isFull() { + return ((this.top + 1) & kMask) === this.bottom; + } + + push(data) { + this.list[this.top] = data; + this.top = (this.top + 1) & kMask; + } + + shift() { + const nextItem = this.list[this.bottom]; + if (nextItem === undefined) + return null; + this.list[this.bottom] = undefined; + this.bottom = (this.bottom + 1) & kMask; + return nextItem; + } +} + +module.exports = class FixedQueue { + constructor() { + this.head = this.tail = new FixedCircularBuffer(); + } + + isEmpty() { + return this.head.isEmpty(); + } + + push(data) { + if (this.head.isFull()) { + // Head is full: Creates a new queue, sets the old queue's `.next` to it, + // and sets it as the new main queue. + this.head = this.head.next = new FixedCircularBuffer(); + } + this.head.push(data); + } + + shift() { + const tail = this.tail; + const next = tail.shift(); + if (tail.isEmpty() && tail.next !== null) { + // If there is another queue, it forms the new tail. + this.tail = tail.next; + } + return next; + } +}; + + +/***/ }), + +/***/ 8617: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const DispatcherBase = __nccwpck_require__(8462) +const FixedQueue = __nccwpck_require__(6937) +const { kConnected, kSize, kRunning, kPending, kQueued, kBusy, kFree, kUrl, kClose, kDestroy, kDispatch } = __nccwpck_require__(9440) +const PoolStats = __nccwpck_require__(925) + +const kClients = Symbol('clients') +const kNeedDrain = Symbol('needDrain') +const kQueue = Symbol('queue') +const kClosedResolve = Symbol('closed resolve') +const kOnDrain = Symbol('onDrain') +const kOnConnect = Symbol('onConnect') +const kOnDisconnect = Symbol('onDisconnect') +const kOnConnectionError = Symbol('onConnectionError') +const kGetDispatcher = Symbol('get dispatcher') +const kAddClient = Symbol('add client') +const kRemoveClient = Symbol('remove client') +const kStats = Symbol('stats') + +class PoolBase extends DispatcherBase { + constructor () { + super() + + this[kQueue] = new FixedQueue() + this[kClients] = [] + this[kQueued] = 0 + + const pool = this + + this[kOnDrain] = function onDrain (origin, targets) { + const queue = pool[kQueue] + + let needDrain = false + + while (!needDrain) { + const item = queue.shift() + if (!item) { + break + } + pool[kQueued]-- + needDrain = !this.dispatch(item.opts, item.handler) + } + + this[kNeedDrain] = needDrain + + if (!this[kNeedDrain] && pool[kNeedDrain]) { + pool[kNeedDrain] = false + pool.emit('drain', origin, [pool, ...targets]) + } + + if (pool[kClosedResolve] && queue.isEmpty()) { + Promise + .all(pool[kClients].map(c => c.close())) + .then(pool[kClosedResolve]) + } + } + + this[kOnConnect] = (origin, targets) => { + pool.emit('connect', origin, [pool, ...targets]) + } + + this[kOnDisconnect] = (origin, targets, err) => { + pool.emit('disconnect', origin, [pool, ...targets], err) + } + + this[kOnConnectionError] = (origin, targets, err) => { + pool.emit('connectionError', origin, [pool, ...targets], err) + } + + this[kStats] = new PoolStats(this) + } + + get [kBusy] () { + return this[kNeedDrain] + } + + get [kConnected] () { + return this[kClients].filter(client => client[kConnected]).length + } + + get [kFree] () { + return this[kClients].filter(client => client[kConnected] && !client[kNeedDrain]).length + } + + get [kPending] () { + let ret = this[kQueued] + for (const { [kPending]: pending } of this[kClients]) { + ret += pending + } + return ret + } + + get [kRunning] () { + let ret = 0 + for (const { [kRunning]: running } of this[kClients]) { + ret += running + } + return ret + } + + get [kSize] () { + let ret = this[kQueued] + for (const { [kSize]: size } of this[kClients]) { + ret += size + } + return ret + } + + get stats () { + return this[kStats] + } + + async [kClose] () { + if (this[kQueue].isEmpty()) { + return Promise.all(this[kClients].map(c => c.close())) + } else { + return new Promise((resolve) => { + this[kClosedResolve] = resolve + }) + } + } + + async [kDestroy] (err) { + while (true) { + const item = this[kQueue].shift() + if (!item) { + break + } + item.handler.onError(err) + } + + return Promise.all(this[kClients].map(c => c.destroy(err))) + } + + [kDispatch] (opts, handler) { + const dispatcher = this[kGetDispatcher]() + + if (!dispatcher) { + this[kNeedDrain] = true + this[kQueue].push({ opts, handler }) + this[kQueued]++ + } else if (!dispatcher.dispatch(opts, handler)) { + dispatcher[kNeedDrain] = true + this[kNeedDrain] = !this[kGetDispatcher]() + } + + return !this[kNeedDrain] + } + + [kAddClient] (client) { + client + .on('drain', this[kOnDrain]) + .on('connect', this[kOnConnect]) + .on('disconnect', this[kOnDisconnect]) + .on('connectionError', this[kOnConnectionError]) + + this[kClients].push(client) + + if (this[kNeedDrain]) { + process.nextTick(() => { + if (this[kNeedDrain]) { + this[kOnDrain](client[kUrl], [this, client]) + } + }) + } + + return this + } + + [kRemoveClient] (client) { + client.close(() => { + const idx = this[kClients].indexOf(client) + if (idx !== -1) { + this[kClients].splice(idx, 1) + } + }) + + this[kNeedDrain] = this[kClients].some(dispatcher => ( + !dispatcher[kNeedDrain] && + dispatcher.closed !== true && + dispatcher.destroyed !== true + )) + } +} + +module.exports = { + PoolBase, + kClients, + kNeedDrain, + kAddClient, + kRemoveClient, + kGetDispatcher +} + + +/***/ }), + +/***/ 925: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +const { kFree, kConnected, kPending, kQueued, kRunning, kSize } = __nccwpck_require__(9440) +const kPool = Symbol('pool') + +class PoolStats { + constructor (pool) { + this[kPool] = pool + } + + get connected () { + return this[kPool][kConnected] + } + + get free () { + return this[kPool][kFree] + } + + get pending () { + return this[kPool][kPending] + } + + get queued () { + return this[kPool][kQueued] + } + + get running () { + return this[kPool][kRunning] + } + + get size () { + return this[kPool][kSize] + } +} + +module.exports = PoolStats + + +/***/ }), + +/***/ 2395: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { + PoolBase, + kClients, + kNeedDrain, + kAddClient, + kGetDispatcher +} = __nccwpck_require__(8617) +const Client = __nccwpck_require__(1180) +const { + InvalidArgumentError +} = __nccwpck_require__(721) +const util = __nccwpck_require__(9522) +const { kUrl, kInterceptors } = __nccwpck_require__(9440) +const buildConnector = __nccwpck_require__(7530) + +const kOptions = Symbol('options') +const kConnections = Symbol('connections') +const kFactory = Symbol('factory') + +function defaultFactory (origin, opts) { + return new Client(origin, opts) +} + +class Pool extends PoolBase { + constructor (origin, { + connections, + factory = defaultFactory, + connect, + connectTimeout, + tls, + maxCachedSessions, + socketPath, + autoSelectFamily, + autoSelectFamilyAttemptTimeout, + allowH2, + ...options + } = {}) { + super() + + if (connections != null && (!Number.isFinite(connections) || connections < 0)) { + throw new InvalidArgumentError('invalid connections') + } + + if (typeof factory !== 'function') { + throw new InvalidArgumentError('factory must be a function.') + } + + if (connect != null && typeof connect !== 'function' && typeof connect !== 'object') { + throw new InvalidArgumentError('connect must be a function or an object') + } + + if (typeof connect !== 'function') { + connect = buildConnector({ + ...tls, + maxCachedSessions, + allowH2, + socketPath, + timeout: connectTimeout, + ...(util.nodeHasAutoSelectFamily && autoSelectFamily ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : undefined), + ...connect + }) + } + + this[kInterceptors] = options.interceptors && options.interceptors.Pool && Array.isArray(options.interceptors.Pool) + ? options.interceptors.Pool + : [] + this[kConnections] = connections || null + this[kUrl] = util.parseOrigin(origin) + this[kOptions] = { ...util.deepClone(options), connect, allowH2 } + this[kOptions].interceptors = options.interceptors + ? { ...options.interceptors } + : undefined + this[kFactory] = factory + } + + [kGetDispatcher] () { + let dispatcher = this[kClients].find(dispatcher => !dispatcher[kNeedDrain]) + + if (dispatcher) { + return dispatcher + } + + if (!this[kConnections] || this[kClients].length < this[kConnections]) { + dispatcher = this[kFactory](this[kUrl], this[kOptions]) + this[kAddClient](dispatcher) + } + + return dispatcher + } +} + +module.exports = Pool + + +/***/ }), + +/***/ 9391: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { kProxy, kClose, kDestroy, kInterceptors } = __nccwpck_require__(9440) +const { URL } = __nccwpck_require__(7310) +const Agent = __nccwpck_require__(8596) +const Pool = __nccwpck_require__(2395) +const DispatcherBase = __nccwpck_require__(8462) +const { InvalidArgumentError, RequestAbortedError } = __nccwpck_require__(721) +const buildConnector = __nccwpck_require__(7530) + +const kAgent = Symbol('proxy agent') +const kClient = Symbol('proxy client') +const kProxyHeaders = Symbol('proxy headers') +const kRequestTls = Symbol('request tls settings') +const kProxyTls = Symbol('proxy tls settings') +const kConnectEndpoint = Symbol('connect endpoint function') + +function defaultProtocolPort (protocol) { + return protocol === 'https:' ? 443 : 80 +} + +function buildProxyOptions (opts) { + if (typeof opts === 'string') { + opts = { uri: opts } + } + + if (!opts || !opts.uri) { + throw new InvalidArgumentError('Proxy opts.uri is mandatory') + } + + return { + uri: opts.uri, + protocol: opts.protocol || 'https' + } +} + +function defaultFactory (origin, opts) { + return new Pool(origin, opts) +} + +class ProxyAgent extends DispatcherBase { + constructor (opts) { + super(opts) + this[kProxy] = buildProxyOptions(opts) + this[kAgent] = new Agent(opts) + this[kInterceptors] = opts.interceptors && opts.interceptors.ProxyAgent && Array.isArray(opts.interceptors.ProxyAgent) + ? opts.interceptors.ProxyAgent + : [] + + if (typeof opts === 'string') { + opts = { uri: opts } + } + + if (!opts || !opts.uri) { + throw new InvalidArgumentError('Proxy opts.uri is mandatory') + } + + const { clientFactory = defaultFactory } = opts + + if (typeof clientFactory !== 'function') { + throw new InvalidArgumentError('Proxy opts.clientFactory must be a function.') + } + + this[kRequestTls] = opts.requestTls + this[kProxyTls] = opts.proxyTls + this[kProxyHeaders] = opts.headers || {} + + if (opts.auth && opts.token) { + throw new InvalidArgumentError('opts.auth cannot be used in combination with opts.token') + } else if (opts.auth) { + /* @deprecated in favour of opts.token */ + this[kProxyHeaders]['proxy-authorization'] = `Basic ${opts.auth}` + } else if (opts.token) { + this[kProxyHeaders]['proxy-authorization'] = opts.token + } + + const resolvedUrl = new URL(opts.uri) + const { origin, port, host } = resolvedUrl + + const connect = buildConnector({ ...opts.proxyTls }) + this[kConnectEndpoint] = buildConnector({ ...opts.requestTls }) + this[kClient] = clientFactory(resolvedUrl, { connect }) + this[kAgent] = new Agent({ + ...opts, + connect: async (opts, callback) => { + let requestedHost = opts.host + if (!opts.port) { + requestedHost += `:${defaultProtocolPort(opts.protocol)}` + } + try { + const { socket, statusCode } = await this[kClient].connect({ + origin, + port, + path: requestedHost, + signal: opts.signal, + headers: { + ...this[kProxyHeaders], + host + } + }) + if (statusCode !== 200) { + socket.on('error', () => {}).destroy() + callback(new RequestAbortedError('Proxy response !== 200 when HTTP Tunneling')) + } + if (opts.protocol !== 'https:') { + callback(null, socket) + return + } + let servername + if (this[kRequestTls]) { + servername = this[kRequestTls].servername + } else { + servername = opts.servername + } + this[kConnectEndpoint]({ ...opts, servername, httpSocket: socket }, callback) + } catch (err) { + callback(err) + } + } + }) + } + + dispatch (opts, handler) { + const { host } = new URL(opts.origin) + const headers = buildHeaders(opts.headers) + throwIfProxyAuthIsSent(headers) + return this[kAgent].dispatch( + { + ...opts, + headers: { + ...headers, + host + } + }, + handler + ) + } + + async [kClose] () { + await this[kAgent].close() + await this[kClient].close() + } + + async [kDestroy] () { + await this[kAgent].destroy() + await this[kClient].destroy() + } +} + +/** + * @param {string[] | Record} headers + * @returns {Record} + */ +function buildHeaders (headers) { + // When using undici.fetch, the headers list is stored + // as an array. + if (Array.isArray(headers)) { + /** @type {Record} */ + const headersPair = {} + + for (let i = 0; i < headers.length; i += 2) { + headersPair[headers[i]] = headers[i + 1] + } + + return headersPair + } + + return headers +} + +/** + * @param {Record} headers + * + * Previous versions of ProxyAgent suggests the Proxy-Authorization in request headers + * Nevertheless, it was changed and to avoid a security vulnerability by end users + * this check was created. + * It should be removed in the next major version for performance reasons + */ +function throwIfProxyAuthIsSent (headers) { + const existProxyAuth = headers && Object.keys(headers) + .find((key) => key.toLowerCase() === 'proxy-authorization') + if (existProxyAuth) { + throw new InvalidArgumentError('Proxy-Authorization should be sent in ProxyAgent constructor') + } +} + +module.exports = ProxyAgent + + +/***/ }), + +/***/ 883: +/***/ ((module) => { + +"use strict"; + + +let fastNow = Date.now() +let fastNowTimeout + +const fastTimers = [] + +function onTimeout () { + fastNow = Date.now() + + let len = fastTimers.length + let idx = 0 + while (idx < len) { + const timer = fastTimers[idx] + + if (timer.state === 0) { + timer.state = fastNow + timer.delay + } else if (timer.state > 0 && fastNow >= timer.state) { + timer.state = -1 + timer.callback(timer.opaque) + } + + if (timer.state === -1) { + timer.state = -2 + if (idx !== len - 1) { + fastTimers[idx] = fastTimers.pop() + } else { + fastTimers.pop() + } + len -= 1 + } else { + idx += 1 + } + } + + if (fastTimers.length > 0) { + refreshTimeout() + } +} + +function refreshTimeout () { + if (fastNowTimeout && fastNowTimeout.refresh) { + fastNowTimeout.refresh() + } else { + clearTimeout(fastNowTimeout) + fastNowTimeout = setTimeout(onTimeout, 1e3) + if (fastNowTimeout.unref) { + fastNowTimeout.unref() + } + } +} + +class Timeout { + constructor (callback, delay, opaque) { + this.callback = callback + this.delay = delay + this.opaque = opaque + + // -2 not in timer list + // -1 in timer list but inactive + // 0 in timer list waiting for time + // > 0 in timer list waiting for time to expire + this.state = -2 + + this.refresh() + } + + refresh () { + if (this.state === -2) { + fastTimers.push(this) + if (!fastNowTimeout || fastTimers.length === 1) { + refreshTimeout() + } + } + + this.state = 0 + } + + clear () { + this.state = -1 + } +} + +module.exports = { + setTimeout (callback, delay, opaque) { + return delay < 1e3 + ? setTimeout(callback, delay, opaque) + : new Timeout(callback, delay, opaque) + }, + clearTimeout (timeout) { + if (timeout instanceof Timeout) { + timeout.clear() + } else { + clearTimeout(timeout) + } + } +} + + +/***/ }), + +/***/ 6812: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const diagnosticsChannel = __nccwpck_require__(7643) +const { uid, states } = __nccwpck_require__(2223) +const { + kReadyState, + kSentClose, + kByteParser, + kReceivedClose +} = __nccwpck_require__(1560) +const { fireEvent, failWebsocketConnection } = __nccwpck_require__(8014) +const { CloseEvent } = __nccwpck_require__(8015) +const { makeRequest } = __nccwpck_require__(9157) +const { fetching } = __nccwpck_require__(5935) +const { Headers } = __nccwpck_require__(7689) +const { getGlobalDispatcher } = __nccwpck_require__(5035) +const { kHeadersList } = __nccwpck_require__(9440) + +const channels = {} +channels.open = diagnosticsChannel.channel('undici:websocket:open') +channels.close = diagnosticsChannel.channel('undici:websocket:close') +channels.socketError = diagnosticsChannel.channel('undici:websocket:socket_error') + +/** @type {import('crypto')} */ +let crypto +try { + crypto = __nccwpck_require__(6113) +} catch { + +} + +/** + * @see https://websockets.spec.whatwg.org/#concept-websocket-establish + * @param {URL} url + * @param {string|string[]} protocols + * @param {import('./websocket').WebSocket} ws + * @param {(response: any) => void} onEstablish + * @param {Partial} options + */ +function establishWebSocketConnection (url, protocols, ws, onEstablish, options) { + // 1. Let requestURL be a copy of url, with its scheme set to "http", if url’s + // scheme is "ws", and to "https" otherwise. + const requestURL = url + + requestURL.protocol = url.protocol === 'ws:' ? 'http:' : 'https:' + + // 2. Let request be a new request, whose URL is requestURL, client is client, + // service-workers mode is "none", referrer is "no-referrer", mode is + // "websocket", credentials mode is "include", cache mode is "no-store" , + // and redirect mode is "error". + const request = makeRequest({ + urlList: [requestURL], + serviceWorkers: 'none', + referrer: 'no-referrer', + mode: 'websocket', + credentials: 'include', + cache: 'no-store', + redirect: 'error' + }) + + // Note: undici extension, allow setting custom headers. + if (options.headers) { + const headersList = new Headers(options.headers)[kHeadersList] + + request.headersList = headersList + } + + // 3. Append (`Upgrade`, `websocket`) to request’s header list. + // 4. Append (`Connection`, `Upgrade`) to request’s header list. + // Note: both of these are handled by undici currently. + // https://github.com/nodejs/undici/blob/68c269c4144c446f3f1220951338daef4a6b5ec4/lib/client.js#L1397 + + // 5. Let keyValue be a nonce consisting of a randomly selected + // 16-byte value that has been forgiving-base64-encoded and + // isomorphic encoded. + const keyValue = crypto.randomBytes(16).toString('base64') + + // 6. Append (`Sec-WebSocket-Key`, keyValue) to request’s + // header list. + request.headersList.append('sec-websocket-key', keyValue) + + // 7. Append (`Sec-WebSocket-Version`, `13`) to request’s + // header list. + request.headersList.append('sec-websocket-version', '13') + + // 8. For each protocol in protocols, combine + // (`Sec-WebSocket-Protocol`, protocol) in request’s header + // list. + for (const protocol of protocols) { + request.headersList.append('sec-websocket-protocol', protocol) + } + + // 9. Let permessageDeflate be a user-agent defined + // "permessage-deflate" extension header value. + // https://github.com/mozilla/gecko-dev/blob/ce78234f5e653a5d3916813ff990f053510227bc/netwerk/protocol/websocket/WebSocketChannel.cpp#L2673 + // TODO: enable once permessage-deflate is supported + const permessageDeflate = '' // 'permessage-deflate; 15' + + // 10. Append (`Sec-WebSocket-Extensions`, permessageDeflate) to + // request’s header list. + // request.headersList.append('sec-websocket-extensions', permessageDeflate) + + // 11. Fetch request with useParallelQueue set to true, and + // processResponse given response being these steps: + const controller = fetching({ + request, + useParallelQueue: true, + dispatcher: options.dispatcher ?? getGlobalDispatcher(), + processResponse (response) { + // 1. If response is a network error or its status is not 101, + // fail the WebSocket connection. + if (response.type === 'error' || response.status !== 101) { + failWebsocketConnection(ws, 'Received network error or non-101 status code.') + return + } + + // 2. If protocols is not the empty list and extracting header + // list values given `Sec-WebSocket-Protocol` and response’s + // header list results in null, failure, or the empty byte + // sequence, then fail the WebSocket connection. + if (protocols.length !== 0 && !response.headersList.get('Sec-WebSocket-Protocol')) { + failWebsocketConnection(ws, 'Server did not respond with sent protocols.') + return + } + + // 3. Follow the requirements stated step 2 to step 6, inclusive, + // of the last set of steps in section 4.1 of The WebSocket + // Protocol to validate response. This either results in fail + // the WebSocket connection or the WebSocket connection is + // established. + + // 2. If the response lacks an |Upgrade| header field or the |Upgrade| + // header field contains a value that is not an ASCII case- + // insensitive match for the value "websocket", the client MUST + // _Fail the WebSocket Connection_. + if (response.headersList.get('Upgrade')?.toLowerCase() !== 'websocket') { + failWebsocketConnection(ws, 'Server did not set Upgrade header to "websocket".') + return + } + + // 3. If the response lacks a |Connection| header field or the + // |Connection| header field doesn't contain a token that is an + // ASCII case-insensitive match for the value "Upgrade", the client + // MUST _Fail the WebSocket Connection_. + if (response.headersList.get('Connection')?.toLowerCase() !== 'upgrade') { + failWebsocketConnection(ws, 'Server did not set Connection header to "upgrade".') + return + } + + // 4. If the response lacks a |Sec-WebSocket-Accept| header field or + // the |Sec-WebSocket-Accept| contains a value other than the + // base64-encoded SHA-1 of the concatenation of the |Sec-WebSocket- + // Key| (as a string, not base64-decoded) with the string "258EAFA5- + // E914-47DA-95CA-C5AB0DC85B11" but ignoring any leading and + // trailing whitespace, the client MUST _Fail the WebSocket + // Connection_. + const secWSAccept = response.headersList.get('Sec-WebSocket-Accept') + const digest = crypto.createHash('sha1').update(keyValue + uid).digest('base64') + if (secWSAccept !== digest) { + failWebsocketConnection(ws, 'Incorrect hash received in Sec-WebSocket-Accept header.') + return + } + + // 5. If the response includes a |Sec-WebSocket-Extensions| header + // field and this header field indicates the use of an extension + // that was not present in the client's handshake (the server has + // indicated an extension not requested by the client), the client + // MUST _Fail the WebSocket Connection_. (The parsing of this + // header field to determine which extensions are requested is + // discussed in Section 9.1.) + const secExtension = response.headersList.get('Sec-WebSocket-Extensions') + + if (secExtension !== null && secExtension !== permessageDeflate) { + failWebsocketConnection(ws, 'Received different permessage-deflate than the one set.') + return + } + + // 6. If the response includes a |Sec-WebSocket-Protocol| header field + // and this header field indicates the use of a subprotocol that was + // not present in the client's handshake (the server has indicated a + // subprotocol not requested by the client), the client MUST _Fail + // the WebSocket Connection_. + const secProtocol = response.headersList.get('Sec-WebSocket-Protocol') + + if (secProtocol !== null && secProtocol !== request.headersList.get('Sec-WebSocket-Protocol')) { + failWebsocketConnection(ws, 'Protocol was not set in the opening handshake.') + return + } + + response.socket.on('data', onSocketData) + response.socket.on('close', onSocketClose) + response.socket.on('error', onSocketError) + + if (channels.open.hasSubscribers) { + channels.open.publish({ + address: response.socket.address(), + protocol: secProtocol, + extensions: secExtension + }) + } + + onEstablish(response) + } + }) + + return controller +} + +/** + * @param {Buffer} chunk + */ +function onSocketData (chunk) { + if (!this.ws[kByteParser].write(chunk)) { + this.pause() + } +} + +/** + * @see https://websockets.spec.whatwg.org/#feedback-from-the-protocol + * @see https://datatracker.ietf.org/doc/html/rfc6455#section-7.1.4 + */ +function onSocketClose () { + const { ws } = this + + // If the TCP connection was closed after the + // WebSocket closing handshake was completed, the WebSocket connection + // is said to have been closed _cleanly_. + const wasClean = ws[kSentClose] && ws[kReceivedClose] + + let code = 1005 + let reason = '' + + const result = ws[kByteParser].closingInfo + + if (result) { + code = result.code ?? 1005 + reason = result.reason + } else if (!ws[kSentClose]) { + // If _The WebSocket + // Connection is Closed_ and no Close control frame was received by the + // endpoint (such as could occur if the underlying transport connection + // is lost), _The WebSocket Connection Close Code_ is considered to be + // 1006. + code = 1006 + } + + // 1. Change the ready state to CLOSED (3). + ws[kReadyState] = states.CLOSED + + // 2. If the user agent was required to fail the WebSocket + // connection, or if the WebSocket connection was closed + // after being flagged as full, fire an event named error + // at the WebSocket object. + // TODO + + // 3. Fire an event named close at the WebSocket object, + // using CloseEvent, with the wasClean attribute + // initialized to true if the connection closed cleanly + // and false otherwise, the code attribute initialized to + // the WebSocket connection close code, and the reason + // attribute initialized to the result of applying UTF-8 + // decode without BOM to the WebSocket connection close + // reason. + fireEvent('close', ws, CloseEvent, { + wasClean, code, reason + }) + + if (channels.close.hasSubscribers) { + channels.close.publish({ + websocket: ws, + code, + reason + }) + } +} + +function onSocketError (error) { + const { ws } = this + + ws[kReadyState] = states.CLOSING + + if (channels.socketError.hasSubscribers) { + channels.socketError.publish(error) + } + + this.destroy() +} + +module.exports = { + establishWebSocketConnection +} + + +/***/ }), + +/***/ 2223: +/***/ ((module) => { + +"use strict"; + + +// This is a Globally Unique Identifier unique used +// to validate that the endpoint accepts websocket +// connections. +// See https://www.rfc-editor.org/rfc/rfc6455.html#section-1.3 +const uid = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11' + +/** @type {PropertyDescriptor} */ +const staticPropertyDescriptors = { + enumerable: true, + writable: false, + configurable: false +} + +const states = { + CONNECTING: 0, + OPEN: 1, + CLOSING: 2, + CLOSED: 3 +} + +const opcodes = { + CONTINUATION: 0x0, + TEXT: 0x1, + BINARY: 0x2, + CLOSE: 0x8, + PING: 0x9, + PONG: 0xA +} + +const maxUnsigned16Bit = 2 ** 16 - 1 // 65535 + +const parserStates = { + INFO: 0, + PAYLOADLENGTH_16: 2, + PAYLOADLENGTH_64: 3, + READ_DATA: 4 +} + +const emptyBuffer = Buffer.allocUnsafe(0) + +module.exports = { + uid, + staticPropertyDescriptors, + states, + opcodes, + maxUnsigned16Bit, + parserStates, + emptyBuffer +} + + +/***/ }), + +/***/ 8015: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { webidl } = __nccwpck_require__(1537) +const { kEnumerableProperty } = __nccwpck_require__(9522) +const { MessagePort } = __nccwpck_require__(1267) + +/** + * @see https://html.spec.whatwg.org/multipage/comms.html#messageevent + */ +class MessageEvent extends Event { + #eventInit + + constructor (type, eventInitDict = {}) { + webidl.argumentLengthCheck(arguments, 1, { header: 'MessageEvent constructor' }) + + type = webidl.converters.DOMString(type) + eventInitDict = webidl.converters.MessageEventInit(eventInitDict) + + super(type, eventInitDict) + + this.#eventInit = eventInitDict + } + + get data () { + webidl.brandCheck(this, MessageEvent) + + return this.#eventInit.data + } + + get origin () { + webidl.brandCheck(this, MessageEvent) + + return this.#eventInit.origin + } + + get lastEventId () { + webidl.brandCheck(this, MessageEvent) + + return this.#eventInit.lastEventId + } + + get source () { + webidl.brandCheck(this, MessageEvent) + + return this.#eventInit.source + } + + get ports () { + webidl.brandCheck(this, MessageEvent) + + if (!Object.isFrozen(this.#eventInit.ports)) { + Object.freeze(this.#eventInit.ports) + } + + return this.#eventInit.ports + } + + initMessageEvent ( + type, + bubbles = false, + cancelable = false, + data = null, + origin = '', + lastEventId = '', + source = null, + ports = [] + ) { + webidl.brandCheck(this, MessageEvent) + + webidl.argumentLengthCheck(arguments, 1, { header: 'MessageEvent.initMessageEvent' }) + + return new MessageEvent(type, { + bubbles, cancelable, data, origin, lastEventId, source, ports + }) + } +} + +/** + * @see https://websockets.spec.whatwg.org/#the-closeevent-interface + */ +class CloseEvent extends Event { + #eventInit + + constructor (type, eventInitDict = {}) { + webidl.argumentLengthCheck(arguments, 1, { header: 'CloseEvent constructor' }) + + type = webidl.converters.DOMString(type) + eventInitDict = webidl.converters.CloseEventInit(eventInitDict) + + super(type, eventInitDict) + + this.#eventInit = eventInitDict + } + + get wasClean () { + webidl.brandCheck(this, CloseEvent) + + return this.#eventInit.wasClean + } + + get code () { + webidl.brandCheck(this, CloseEvent) + + return this.#eventInit.code + } + + get reason () { + webidl.brandCheck(this, CloseEvent) + + return this.#eventInit.reason + } +} + +// https://html.spec.whatwg.org/multipage/webappapis.html#the-errorevent-interface +class ErrorEvent extends Event { + #eventInit + + constructor (type, eventInitDict) { + webidl.argumentLengthCheck(arguments, 1, { header: 'ErrorEvent constructor' }) + + super(type, eventInitDict) + + type = webidl.converters.DOMString(type) + eventInitDict = webidl.converters.ErrorEventInit(eventInitDict ?? {}) + + this.#eventInit = eventInitDict + } + + get message () { + webidl.brandCheck(this, ErrorEvent) + + return this.#eventInit.message + } + + get filename () { + webidl.brandCheck(this, ErrorEvent) + + return this.#eventInit.filename + } + + get lineno () { + webidl.brandCheck(this, ErrorEvent) + + return this.#eventInit.lineno + } + + get colno () { + webidl.brandCheck(this, ErrorEvent) + + return this.#eventInit.colno + } + + get error () { + webidl.brandCheck(this, ErrorEvent) + + return this.#eventInit.error + } +} + +Object.defineProperties(MessageEvent.prototype, { + [Symbol.toStringTag]: { + value: 'MessageEvent', + configurable: true + }, + data: kEnumerableProperty, + origin: kEnumerableProperty, + lastEventId: kEnumerableProperty, + source: kEnumerableProperty, + ports: kEnumerableProperty, + initMessageEvent: kEnumerableProperty +}) + +Object.defineProperties(CloseEvent.prototype, { + [Symbol.toStringTag]: { + value: 'CloseEvent', + configurable: true + }, + reason: kEnumerableProperty, + code: kEnumerableProperty, + wasClean: kEnumerableProperty +}) + +Object.defineProperties(ErrorEvent.prototype, { + [Symbol.toStringTag]: { + value: 'ErrorEvent', + configurable: true + }, + message: kEnumerableProperty, + filename: kEnumerableProperty, + lineno: kEnumerableProperty, + colno: kEnumerableProperty, + error: kEnumerableProperty +}) + +webidl.converters.MessagePort = webidl.interfaceConverter(MessagePort) + +webidl.converters['sequence'] = webidl.sequenceConverter( + webidl.converters.MessagePort +) + +const eventInit = [ + { + key: 'bubbles', + converter: webidl.converters.boolean, + defaultValue: false + }, + { + key: 'cancelable', + converter: webidl.converters.boolean, + defaultValue: false + }, + { + key: 'composed', + converter: webidl.converters.boolean, + defaultValue: false + } +] + +webidl.converters.MessageEventInit = webidl.dictionaryConverter([ + ...eventInit, + { + key: 'data', + converter: webidl.converters.any, + defaultValue: null + }, + { + key: 'origin', + converter: webidl.converters.USVString, + defaultValue: '' + }, + { + key: 'lastEventId', + converter: webidl.converters.DOMString, + defaultValue: '' + }, + { + key: 'source', + // Node doesn't implement WindowProxy or ServiceWorker, so the only + // valid value for source is a MessagePort. + converter: webidl.nullableConverter(webidl.converters.MessagePort), + defaultValue: null + }, + { + key: 'ports', + converter: webidl.converters['sequence'], + get defaultValue () { + return [] + } + } +]) + +webidl.converters.CloseEventInit = webidl.dictionaryConverter([ + ...eventInit, + { + key: 'wasClean', + converter: webidl.converters.boolean, + defaultValue: false + }, + { + key: 'code', + converter: webidl.converters['unsigned short'], + defaultValue: 0 + }, + { + key: 'reason', + converter: webidl.converters.USVString, + defaultValue: '' + } +]) + +webidl.converters.ErrorEventInit = webidl.dictionaryConverter([ + ...eventInit, + { + key: 'message', + converter: webidl.converters.DOMString, + defaultValue: '' + }, + { + key: 'filename', + converter: webidl.converters.USVString, + defaultValue: '' + }, + { + key: 'lineno', + converter: webidl.converters['unsigned long'], + defaultValue: 0 + }, + { + key: 'colno', + converter: webidl.converters['unsigned long'], + defaultValue: 0 + }, + { + key: 'error', + converter: webidl.converters.any + } +]) + +module.exports = { + MessageEvent, + CloseEvent, + ErrorEvent +} + + +/***/ }), + +/***/ 2412: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { maxUnsigned16Bit } = __nccwpck_require__(2223) + +/** @type {import('crypto')} */ +let crypto +try { + crypto = __nccwpck_require__(6113) +} catch { + +} + +class WebsocketFrameSend { + /** + * @param {Buffer|undefined} data + */ + constructor (data) { + this.frameData = data + this.maskKey = crypto.randomBytes(4) + } + + createFrame (opcode) { + const bodyLength = this.frameData?.byteLength ?? 0 + + /** @type {number} */ + let payloadLength = bodyLength // 0-125 + let offset = 6 + + if (bodyLength > maxUnsigned16Bit) { + offset += 8 // payload length is next 8 bytes + payloadLength = 127 + } else if (bodyLength > 125) { + offset += 2 // payload length is next 2 bytes + payloadLength = 126 + } + + const buffer = Buffer.allocUnsafe(bodyLength + offset) + + // Clear first 2 bytes, everything else is overwritten + buffer[0] = buffer[1] = 0 + buffer[0] |= 0x80 // FIN + buffer[0] = (buffer[0] & 0xF0) + opcode // opcode + + /*! ws. MIT License. Einar Otto Stangvik */ + buffer[offset - 4] = this.maskKey[0] + buffer[offset - 3] = this.maskKey[1] + buffer[offset - 2] = this.maskKey[2] + buffer[offset - 1] = this.maskKey[3] + + buffer[1] = payloadLength + + if (payloadLength === 126) { + buffer.writeUInt16BE(bodyLength, 2) + } else if (payloadLength === 127) { + // Clear extended payload length + buffer[2] = buffer[3] = 0 + buffer.writeUIntBE(bodyLength, 4, 6) + } + + buffer[1] |= 0x80 // MASK + + // mask body + for (let i = 0; i < bodyLength; i++) { + buffer[offset + i] = this.frameData[i] ^ this.maskKey[i % 4] + } + + return buffer + } +} + +module.exports = { + WebsocketFrameSend +} + + +/***/ }), + +/***/ 1731: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { Writable } = __nccwpck_require__(2781) +const diagnosticsChannel = __nccwpck_require__(7643) +const { parserStates, opcodes, states, emptyBuffer } = __nccwpck_require__(2223) +const { kReadyState, kSentClose, kResponse, kReceivedClose } = __nccwpck_require__(1560) +const { isValidStatusCode, failWebsocketConnection, websocketMessageReceived } = __nccwpck_require__(8014) +const { WebsocketFrameSend } = __nccwpck_require__(2412) + +// This code was influenced by ws released under the MIT license. +// Copyright (c) 2011 Einar Otto Stangvik +// Copyright (c) 2013 Arnout Kazemier and contributors +// Copyright (c) 2016 Luigi Pinca and contributors + +const channels = {} +channels.ping = diagnosticsChannel.channel('undici:websocket:ping') +channels.pong = diagnosticsChannel.channel('undici:websocket:pong') + +class ByteParser extends Writable { + #buffers = [] + #byteOffset = 0 + + #state = parserStates.INFO + + #info = {} + #fragments = [] + + constructor (ws) { + super() + + this.ws = ws + } + + /** + * @param {Buffer} chunk + * @param {() => void} callback + */ + _write (chunk, _, callback) { + this.#buffers.push(chunk) + this.#byteOffset += chunk.length + + this.run(callback) + } + + /** + * Runs whenever a new chunk is received. + * Callback is called whenever there are no more chunks buffering, + * or not enough bytes are buffered to parse. + */ + run (callback) { + while (true) { + if (this.#state === parserStates.INFO) { + // If there aren't enough bytes to parse the payload length, etc. + if (this.#byteOffset < 2) { + return callback() + } + + const buffer = this.consume(2) + + this.#info.fin = (buffer[0] & 0x80) !== 0 + this.#info.opcode = buffer[0] & 0x0F + + // If we receive a fragmented message, we use the type of the first + // frame to parse the full message as binary/text, when it's terminated + this.#info.originalOpcode ??= this.#info.opcode + + this.#info.fragmented = !this.#info.fin && this.#info.opcode !== opcodes.CONTINUATION + + if (this.#info.fragmented && this.#info.opcode !== opcodes.BINARY && this.#info.opcode !== opcodes.TEXT) { + // Only text and binary frames can be fragmented + failWebsocketConnection(this.ws, 'Invalid frame type was fragmented.') + return + } + + const payloadLength = buffer[1] & 0x7F + + if (payloadLength <= 125) { + this.#info.payloadLength = payloadLength + this.#state = parserStates.READ_DATA + } else if (payloadLength === 126) { + this.#state = parserStates.PAYLOADLENGTH_16 + } else if (payloadLength === 127) { + this.#state = parserStates.PAYLOADLENGTH_64 + } + + if (this.#info.fragmented && payloadLength > 125) { + // A fragmented frame can't be fragmented itself + failWebsocketConnection(this.ws, 'Fragmented frame exceeded 125 bytes.') + return + } else if ( + (this.#info.opcode === opcodes.PING || + this.#info.opcode === opcodes.PONG || + this.#info.opcode === opcodes.CLOSE) && + payloadLength > 125 + ) { + // Control frames can have a payload length of 125 bytes MAX + failWebsocketConnection(this.ws, 'Payload length for control frame exceeded 125 bytes.') + return + } else if (this.#info.opcode === opcodes.CLOSE) { + if (payloadLength === 1) { + failWebsocketConnection(this.ws, 'Received close frame with a 1-byte body.') + return + } + + const body = this.consume(payloadLength) + + this.#info.closeInfo = this.parseCloseBody(false, body) + + if (!this.ws[kSentClose]) { + // If an endpoint receives a Close frame and did not previously send a + // Close frame, the endpoint MUST send a Close frame in response. (When + // sending a Close frame in response, the endpoint typically echos the + // status code it received.) + const body = Buffer.allocUnsafe(2) + body.writeUInt16BE(this.#info.closeInfo.code, 0) + const closeFrame = new WebsocketFrameSend(body) + + this.ws[kResponse].socket.write( + closeFrame.createFrame(opcodes.CLOSE), + (err) => { + if (!err) { + this.ws[kSentClose] = true + } + } + ) + } + + // Upon either sending or receiving a Close control frame, it is said + // that _The WebSocket Closing Handshake is Started_ and that the + // WebSocket connection is in the CLOSING state. + this.ws[kReadyState] = states.CLOSING + this.ws[kReceivedClose] = true + + this.end() + + return + } else if (this.#info.opcode === opcodes.PING) { + // Upon receipt of a Ping frame, an endpoint MUST send a Pong frame in + // response, unless it already received a Close frame. + // A Pong frame sent in response to a Ping frame must have identical + // "Application data" + + const body = this.consume(payloadLength) + + if (!this.ws[kReceivedClose]) { + const frame = new WebsocketFrameSend(body) + + this.ws[kResponse].socket.write(frame.createFrame(opcodes.PONG)) + + if (channels.ping.hasSubscribers) { + channels.ping.publish({ + payload: body + }) + } + } + + this.#state = parserStates.INFO + + if (this.#byteOffset > 0) { + continue + } else { + callback() + return + } + } else if (this.#info.opcode === opcodes.PONG) { + // A Pong frame MAY be sent unsolicited. This serves as a + // unidirectional heartbeat. A response to an unsolicited Pong frame is + // not expected. + + const body = this.consume(payloadLength) + + if (channels.pong.hasSubscribers) { + channels.pong.publish({ + payload: body + }) + } + + if (this.#byteOffset > 0) { + continue + } else { + callback() + return + } + } + } else if (this.#state === parserStates.PAYLOADLENGTH_16) { + if (this.#byteOffset < 2) { + return callback() + } + + const buffer = this.consume(2) + + this.#info.payloadLength = buffer.readUInt16BE(0) + this.#state = parserStates.READ_DATA + } else if (this.#state === parserStates.PAYLOADLENGTH_64) { + if (this.#byteOffset < 8) { + return callback() + } + + const buffer = this.consume(8) + const upper = buffer.readUInt32BE(0) + + // 2^31 is the maxinimum bytes an arraybuffer can contain + // on 32-bit systems. Although, on 64-bit systems, this is + // 2^53-1 bytes. + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Invalid_array_length + // https://source.chromium.org/chromium/chromium/src/+/main:v8/src/common/globals.h;drc=1946212ac0100668f14eb9e2843bdd846e510a1e;bpv=1;bpt=1;l=1275 + // https://source.chromium.org/chromium/chromium/src/+/main:v8/src/objects/js-array-buffer.h;l=34;drc=1946212ac0100668f14eb9e2843bdd846e510a1e + if (upper > 2 ** 31 - 1) { + failWebsocketConnection(this.ws, 'Received payload length > 2^31 bytes.') + return + } + + const lower = buffer.readUInt32BE(4) + + this.#info.payloadLength = (upper << 8) + lower + this.#state = parserStates.READ_DATA + } else if (this.#state === parserStates.READ_DATA) { + if (this.#byteOffset < this.#info.payloadLength) { + // If there is still more data in this chunk that needs to be read + return callback() + } else if (this.#byteOffset >= this.#info.payloadLength) { + // If the server sent multiple frames in a single chunk + + const body = this.consume(this.#info.payloadLength) + + this.#fragments.push(body) + + // If the frame is unfragmented, or a fragmented frame was terminated, + // a message was received + if (!this.#info.fragmented || (this.#info.fin && this.#info.opcode === opcodes.CONTINUATION)) { + const fullMessage = Buffer.concat(this.#fragments) + + websocketMessageReceived(this.ws, this.#info.originalOpcode, fullMessage) + + this.#info = {} + this.#fragments.length = 0 + } + + this.#state = parserStates.INFO + } + } + + if (this.#byteOffset > 0) { + continue + } else { + callback() + break + } + } + } + + /** + * Take n bytes from the buffered Buffers + * @param {number} n + * @returns {Buffer|null} + */ + consume (n) { + if (n > this.#byteOffset) { + return null + } else if (n === 0) { + return emptyBuffer + } + + if (this.#buffers[0].length === n) { + this.#byteOffset -= this.#buffers[0].length + return this.#buffers.shift() + } + + const buffer = Buffer.allocUnsafe(n) + let offset = 0 + + while (offset !== n) { + const next = this.#buffers[0] + const { length } = next + + if (length + offset === n) { + buffer.set(this.#buffers.shift(), offset) + break + } else if (length + offset > n) { + buffer.set(next.subarray(0, n - offset), offset) + this.#buffers[0] = next.subarray(n - offset) + break + } else { + buffer.set(this.#buffers.shift(), offset) + offset += next.length + } + } + + this.#byteOffset -= n + + return buffer + } + + parseCloseBody (onlyCode, data) { + // https://datatracker.ietf.org/doc/html/rfc6455#section-7.1.5 + /** @type {number|undefined} */ + let code + + if (data.length >= 2) { + // _The WebSocket Connection Close Code_ is + // defined as the status code (Section 7.4) contained in the first Close + // control frame received by the application + code = data.readUInt16BE(0) + } + + if (onlyCode) { + if (!isValidStatusCode(code)) { + return null + } + + return { code } + } + + // https://datatracker.ietf.org/doc/html/rfc6455#section-7.1.6 + /** @type {Buffer} */ + let reason = data.subarray(2) + + // Remove BOM + if (reason[0] === 0xEF && reason[1] === 0xBB && reason[2] === 0xBF) { + reason = reason.subarray(3) + } + + if (code !== undefined && !isValidStatusCode(code)) { + return null + } + + try { + // TODO: optimize this + reason = new TextDecoder('utf-8', { fatal: true }).decode(reason) + } catch { + return null + } + + return { code, reason } + } + + get closingInfo () { + return this.#info.closeInfo + } +} + +module.exports = { + ByteParser +} + + +/***/ }), + +/***/ 1560: +/***/ ((module) => { + +"use strict"; + + +module.exports = { + kWebSocketURL: Symbol('url'), + kReadyState: Symbol('ready state'), + kController: Symbol('controller'), + kResponse: Symbol('response'), + kBinaryType: Symbol('binary type'), + kSentClose: Symbol('sent close'), + kReceivedClose: Symbol('received close'), + kByteParser: Symbol('byte parser') +} + + +/***/ }), + +/***/ 8014: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { kReadyState, kController, kResponse, kBinaryType, kWebSocketURL } = __nccwpck_require__(1560) +const { states, opcodes } = __nccwpck_require__(2223) +const { MessageEvent, ErrorEvent } = __nccwpck_require__(8015) + +/* globals Blob */ + +/** + * @param {import('./websocket').WebSocket} ws + */ +function isEstablished (ws) { + // If the server's response is validated as provided for above, it is + // said that _The WebSocket Connection is Established_ and that the + // WebSocket Connection is in the OPEN state. + return ws[kReadyState] === states.OPEN +} + +/** + * @param {import('./websocket').WebSocket} ws + */ +function isClosing (ws) { + // Upon either sending or receiving a Close control frame, it is said + // that _The WebSocket Closing Handshake is Started_ and that the + // WebSocket connection is in the CLOSING state. + return ws[kReadyState] === states.CLOSING +} + +/** + * @param {import('./websocket').WebSocket} ws + */ +function isClosed (ws) { + return ws[kReadyState] === states.CLOSED +} + +/** + * @see https://dom.spec.whatwg.org/#concept-event-fire + * @param {string} e + * @param {EventTarget} target + * @param {EventInit | undefined} eventInitDict + */ +function fireEvent (e, target, eventConstructor = Event, eventInitDict) { + // 1. If eventConstructor is not given, then let eventConstructor be Event. + + // 2. Let event be the result of creating an event given eventConstructor, + // in the relevant realm of target. + // 3. Initialize event’s type attribute to e. + const event = new eventConstructor(e, eventInitDict) // eslint-disable-line new-cap + + // 4. Initialize any other IDL attributes of event as described in the + // invocation of this algorithm. + + // 5. Return the result of dispatching event at target, with legacy target + // override flag set if set. + target.dispatchEvent(event) +} + +/** + * @see https://websockets.spec.whatwg.org/#feedback-from-the-protocol + * @param {import('./websocket').WebSocket} ws + * @param {number} type Opcode + * @param {Buffer} data application data + */ +function websocketMessageReceived (ws, type, data) { + // 1. If ready state is not OPEN (1), then return. + if (ws[kReadyState] !== states.OPEN) { + return + } + + // 2. Let dataForEvent be determined by switching on type and binary type: + let dataForEvent + + if (type === opcodes.TEXT) { + // -> type indicates that the data is Text + // a new DOMString containing data + try { + dataForEvent = new TextDecoder('utf-8', { fatal: true }).decode(data) + } catch { + failWebsocketConnection(ws, 'Received invalid UTF-8 in text frame.') + return + } + } else if (type === opcodes.BINARY) { + if (ws[kBinaryType] === 'blob') { + // -> type indicates that the data is Binary and binary type is "blob" + // a new Blob object, created in the relevant Realm of the WebSocket + // object, that represents data as its raw data + dataForEvent = new Blob([data]) + } else { + // -> type indicates that the data is Binary and binary type is "arraybuffer" + // a new ArrayBuffer object, created in the relevant Realm of the + // WebSocket object, whose contents are data + dataForEvent = new Uint8Array(data).buffer + } + } + + // 3. Fire an event named message at the WebSocket object, using MessageEvent, + // with the origin attribute initialized to the serialization of the WebSocket + // object’s url's origin, and the data attribute initialized to dataForEvent. + fireEvent('message', ws, MessageEvent, { + origin: ws[kWebSocketURL].origin, + data: dataForEvent + }) +} + +/** + * @see https://datatracker.ietf.org/doc/html/rfc6455 + * @see https://datatracker.ietf.org/doc/html/rfc2616 + * @see https://bugs.chromium.org/p/chromium/issues/detail?id=398407 + * @param {string} protocol + */ +function isValidSubprotocol (protocol) { + // If present, this value indicates one + // or more comma-separated subprotocol the client wishes to speak, + // ordered by preference. The elements that comprise this value + // MUST be non-empty strings with characters in the range U+0021 to + // U+007E not including separator characters as defined in + // [RFC2616] and MUST all be unique strings. + if (protocol.length === 0) { + return false + } + + for (const char of protocol) { + const code = char.charCodeAt(0) + + if ( + code < 0x21 || + code > 0x7E || + char === '(' || + char === ')' || + char === '<' || + char === '>' || + char === '@' || + char === ',' || + char === ';' || + char === ':' || + char === '\\' || + char === '"' || + char === '/' || + char === '[' || + char === ']' || + char === '?' || + char === '=' || + char === '{' || + char === '}' || + code === 32 || // SP + code === 9 // HT + ) { + return false + } + } + + return true +} + +/** + * @see https://datatracker.ietf.org/doc/html/rfc6455#section-7-4 + * @param {number} code + */ +function isValidStatusCode (code) { + if (code >= 1000 && code < 1015) { + return ( + code !== 1004 && // reserved + code !== 1005 && // "MUST NOT be set as a status code" + code !== 1006 // "MUST NOT be set as a status code" + ) + } + + return code >= 3000 && code <= 4999 +} + +/** + * @param {import('./websocket').WebSocket} ws + * @param {string|undefined} reason + */ +function failWebsocketConnection (ws, reason) { + const { [kController]: controller, [kResponse]: response } = ws + + controller.abort() + + if (response?.socket && !response.socket.destroyed) { + response.socket.destroy() + } + + if (reason) { + fireEvent('error', ws, ErrorEvent, { + error: new Error(reason) + }) + } +} + +module.exports = { + isEstablished, + isClosing, + isClosed, + fireEvent, + isValidSubprotocol, + isValidStatusCode, + failWebsocketConnection, + websocketMessageReceived +} + + +/***/ }), + +/***/ 7936: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { webidl } = __nccwpck_require__(1537) +const { DOMException } = __nccwpck_require__(7059) +const { URLSerializer } = __nccwpck_require__(2791) +const { getGlobalOrigin } = __nccwpck_require__(5799) +const { staticPropertyDescriptors, states, opcodes, emptyBuffer } = __nccwpck_require__(2223) +const { + kWebSocketURL, + kReadyState, + kController, + kBinaryType, + kResponse, + kSentClose, + kByteParser +} = __nccwpck_require__(1560) +const { isEstablished, isClosing, isValidSubprotocol, failWebsocketConnection, fireEvent } = __nccwpck_require__(8014) +const { establishWebSocketConnection } = __nccwpck_require__(6812) +const { WebsocketFrameSend } = __nccwpck_require__(2412) +const { ByteParser } = __nccwpck_require__(1731) +const { kEnumerableProperty, isBlobLike } = __nccwpck_require__(9522) +const { getGlobalDispatcher } = __nccwpck_require__(5035) +const { types } = __nccwpck_require__(3837) + +let experimentalWarned = false + +// https://websockets.spec.whatwg.org/#interface-definition +class WebSocket extends EventTarget { + #events = { + open: null, + error: null, + close: null, + message: null + } + + #bufferedAmount = 0 + #protocol = '' + #extensions = '' + + /** + * @param {string} url + * @param {string|string[]} protocols + */ + constructor (url, protocols = []) { + super() + + webidl.argumentLengthCheck(arguments, 1, { header: 'WebSocket constructor' }) + + if (!experimentalWarned) { + experimentalWarned = true + process.emitWarning('WebSockets are experimental, expect them to change at any time.', { + code: 'UNDICI-WS' + }) + } + + const options = webidl.converters['DOMString or sequence or WebSocketInit'](protocols) + + url = webidl.converters.USVString(url) + protocols = options.protocols + + // 1. Let baseURL be this's relevant settings object's API base URL. + const baseURL = getGlobalOrigin() + + // 1. Let urlRecord be the result of applying the URL parser to url with baseURL. + let urlRecord + + try { + urlRecord = new URL(url, baseURL) + } catch (e) { + // 3. If urlRecord is failure, then throw a "SyntaxError" DOMException. + throw new DOMException(e, 'SyntaxError') + } + + // 4. If urlRecord’s scheme is "http", then set urlRecord’s scheme to "ws". + if (urlRecord.protocol === 'http:') { + urlRecord.protocol = 'ws:' + } else if (urlRecord.protocol === 'https:') { + // 5. Otherwise, if urlRecord’s scheme is "https", set urlRecord’s scheme to "wss". + urlRecord.protocol = 'wss:' + } + + // 6. If urlRecord’s scheme is not "ws" or "wss", then throw a "SyntaxError" DOMException. + if (urlRecord.protocol !== 'ws:' && urlRecord.protocol !== 'wss:') { + throw new DOMException( + `Expected a ws: or wss: protocol, got ${urlRecord.protocol}`, + 'SyntaxError' + ) + } + + // 7. If urlRecord’s fragment is non-null, then throw a "SyntaxError" + // DOMException. + if (urlRecord.hash || urlRecord.href.endsWith('#')) { + throw new DOMException('Got fragment', 'SyntaxError') + } + + // 8. If protocols is a string, set protocols to a sequence consisting + // of just that string. + if (typeof protocols === 'string') { + protocols = [protocols] + } + + // 9. If any of the values in protocols occur more than once or otherwise + // fail to match the requirements for elements that comprise the value + // of `Sec-WebSocket-Protocol` fields as defined by The WebSocket + // protocol, then throw a "SyntaxError" DOMException. + if (protocols.length !== new Set(protocols.map(p => p.toLowerCase())).size) { + throw new DOMException('Invalid Sec-WebSocket-Protocol value', 'SyntaxError') + } + + if (protocols.length > 0 && !protocols.every(p => isValidSubprotocol(p))) { + throw new DOMException('Invalid Sec-WebSocket-Protocol value', 'SyntaxError') + } + + // 10. Set this's url to urlRecord. + this[kWebSocketURL] = new URL(urlRecord.href) + + // 11. Let client be this's relevant settings object. + + // 12. Run this step in parallel: + + // 1. Establish a WebSocket connection given urlRecord, protocols, + // and client. + this[kController] = establishWebSocketConnection( + urlRecord, + protocols, + this, + (response) => this.#onConnectionEstablished(response), + options + ) + + // Each WebSocket object has an associated ready state, which is a + // number representing the state of the connection. Initially it must + // be CONNECTING (0). + this[kReadyState] = WebSocket.CONNECTING + + // The extensions attribute must initially return the empty string. + + // The protocol attribute must initially return the empty string. + + // Each WebSocket object has an associated binary type, which is a + // BinaryType. Initially it must be "blob". + this[kBinaryType] = 'blob' + } + + /** + * @see https://websockets.spec.whatwg.org/#dom-websocket-close + * @param {number|undefined} code + * @param {string|undefined} reason + */ + close (code = undefined, reason = undefined) { + webidl.brandCheck(this, WebSocket) + + if (code !== undefined) { + code = webidl.converters['unsigned short'](code, { clamp: true }) + } + + if (reason !== undefined) { + reason = webidl.converters.USVString(reason) + } + + // 1. If code is present, but is neither an integer equal to 1000 nor an + // integer in the range 3000 to 4999, inclusive, throw an + // "InvalidAccessError" DOMException. + if (code !== undefined) { + if (code !== 1000 && (code < 3000 || code > 4999)) { + throw new DOMException('invalid code', 'InvalidAccessError') + } + } + + let reasonByteLength = 0 + + // 2. If reason is present, then run these substeps: + if (reason !== undefined) { + // 1. Let reasonBytes be the result of encoding reason. + // 2. If reasonBytes is longer than 123 bytes, then throw a + // "SyntaxError" DOMException. + reasonByteLength = Buffer.byteLength(reason) + + if (reasonByteLength > 123) { + throw new DOMException( + `Reason must be less than 123 bytes; received ${reasonByteLength}`, + 'SyntaxError' + ) + } + } + + // 3. Run the first matching steps from the following list: + if (this[kReadyState] === WebSocket.CLOSING || this[kReadyState] === WebSocket.CLOSED) { + // If this's ready state is CLOSING (2) or CLOSED (3) + // Do nothing. + } else if (!isEstablished(this)) { + // If the WebSocket connection is not yet established + // Fail the WebSocket connection and set this's ready state + // to CLOSING (2). + failWebsocketConnection(this, 'Connection was closed before it was established.') + this[kReadyState] = WebSocket.CLOSING + } else if (!isClosing(this)) { + // If the WebSocket closing handshake has not yet been started + // Start the WebSocket closing handshake and set this's ready + // state to CLOSING (2). + // - If neither code nor reason is present, the WebSocket Close + // message must not have a body. + // - If code is present, then the status code to use in the + // WebSocket Close message must be the integer given by code. + // - If reason is also present, then reasonBytes must be + // provided in the Close message after the status code. + + const frame = new WebsocketFrameSend() + + // If neither code nor reason is present, the WebSocket Close + // message must not have a body. + + // If code is present, then the status code to use in the + // WebSocket Close message must be the integer given by code. + if (code !== undefined && reason === undefined) { + frame.frameData = Buffer.allocUnsafe(2) + frame.frameData.writeUInt16BE(code, 0) + } else if (code !== undefined && reason !== undefined) { + // If reason is also present, then reasonBytes must be + // provided in the Close message after the status code. + frame.frameData = Buffer.allocUnsafe(2 + reasonByteLength) + frame.frameData.writeUInt16BE(code, 0) + // the body MAY contain UTF-8-encoded data with value /reason/ + frame.frameData.write(reason, 2, 'utf-8') + } else { + frame.frameData = emptyBuffer + } + + /** @type {import('stream').Duplex} */ + const socket = this[kResponse].socket + + socket.write(frame.createFrame(opcodes.CLOSE), (err) => { + if (!err) { + this[kSentClose] = true + } + }) + + // Upon either sending or receiving a Close control frame, it is said + // that _The WebSocket Closing Handshake is Started_ and that the + // WebSocket connection is in the CLOSING state. + this[kReadyState] = states.CLOSING + } else { + // Otherwise + // Set this's ready state to CLOSING (2). + this[kReadyState] = WebSocket.CLOSING + } + } + + /** + * @see https://websockets.spec.whatwg.org/#dom-websocket-send + * @param {NodeJS.TypedArray|ArrayBuffer|Blob|string} data + */ + send (data) { + webidl.brandCheck(this, WebSocket) + + webidl.argumentLengthCheck(arguments, 1, { header: 'WebSocket.send' }) + + data = webidl.converters.WebSocketSendData(data) + + // 1. If this's ready state is CONNECTING, then throw an + // "InvalidStateError" DOMException. + if (this[kReadyState] === WebSocket.CONNECTING) { + throw new DOMException('Sent before connected.', 'InvalidStateError') + } + + // 2. Run the appropriate set of steps from the following list: + // https://datatracker.ietf.org/doc/html/rfc6455#section-6.1 + // https://datatracker.ietf.org/doc/html/rfc6455#section-5.2 + + if (!isEstablished(this) || isClosing(this)) { + return + } + + /** @type {import('stream').Duplex} */ + const socket = this[kResponse].socket + + // If data is a string + if (typeof data === 'string') { + // If the WebSocket connection is established and the WebSocket + // closing handshake has not yet started, then the user agent + // must send a WebSocket Message comprised of the data argument + // using a text frame opcode; if the data cannot be sent, e.g. + // because it would need to be buffered but the buffer is full, + // the user agent must flag the WebSocket as full and then close + // the WebSocket connection. Any invocation of this method with a + // string argument that does not throw an exception must increase + // the bufferedAmount attribute by the number of bytes needed to + // express the argument as UTF-8. + + const value = Buffer.from(data) + const frame = new WebsocketFrameSend(value) + const buffer = frame.createFrame(opcodes.TEXT) + + this.#bufferedAmount += value.byteLength + socket.write(buffer, () => { + this.#bufferedAmount -= value.byteLength + }) + } else if (types.isArrayBuffer(data)) { + // If the WebSocket connection is established, and the WebSocket + // closing handshake has not yet started, then the user agent must + // send a WebSocket Message comprised of data using a binary frame + // opcode; if the data cannot be sent, e.g. because it would need + // to be buffered but the buffer is full, the user agent must flag + // the WebSocket as full and then close the WebSocket connection. + // The data to be sent is the data stored in the buffer described + // by the ArrayBuffer object. Any invocation of this method with an + // ArrayBuffer argument that does not throw an exception must + // increase the bufferedAmount attribute by the length of the + // ArrayBuffer in bytes. + + const value = Buffer.from(data) + const frame = new WebsocketFrameSend(value) + const buffer = frame.createFrame(opcodes.BINARY) + + this.#bufferedAmount += value.byteLength + socket.write(buffer, () => { + this.#bufferedAmount -= value.byteLength + }) + } else if (ArrayBuffer.isView(data)) { + // If the WebSocket connection is established, and the WebSocket + // closing handshake has not yet started, then the user agent must + // send a WebSocket Message comprised of data using a binary frame + // opcode; if the data cannot be sent, e.g. because it would need to + // be buffered but the buffer is full, the user agent must flag the + // WebSocket as full and then close the WebSocket connection. The + // data to be sent is the data stored in the section of the buffer + // described by the ArrayBuffer object that data references. Any + // invocation of this method with this kind of argument that does + // not throw an exception must increase the bufferedAmount attribute + // by the length of data’s buffer in bytes. + + const ab = Buffer.from(data, data.byteOffset, data.byteLength) + + const frame = new WebsocketFrameSend(ab) + const buffer = frame.createFrame(opcodes.BINARY) + + this.#bufferedAmount += ab.byteLength + socket.write(buffer, () => { + this.#bufferedAmount -= ab.byteLength + }) + } else if (isBlobLike(data)) { + // If the WebSocket connection is established, and the WebSocket + // closing handshake has not yet started, then the user agent must + // send a WebSocket Message comprised of data using a binary frame + // opcode; if the data cannot be sent, e.g. because it would need to + // be buffered but the buffer is full, the user agent must flag the + // WebSocket as full and then close the WebSocket connection. The data + // to be sent is the raw data represented by the Blob object. Any + // invocation of this method with a Blob argument that does not throw + // an exception must increase the bufferedAmount attribute by the size + // of the Blob object’s raw data, in bytes. + + const frame = new WebsocketFrameSend() + + data.arrayBuffer().then((ab) => { + const value = Buffer.from(ab) + frame.frameData = value + const buffer = frame.createFrame(opcodes.BINARY) + + this.#bufferedAmount += value.byteLength + socket.write(buffer, () => { + this.#bufferedAmount -= value.byteLength + }) + }) + } + } + + get readyState () { + webidl.brandCheck(this, WebSocket) + + // The readyState getter steps are to return this's ready state. + return this[kReadyState] + } + + get bufferedAmount () { + webidl.brandCheck(this, WebSocket) + + return this.#bufferedAmount + } + + get url () { + webidl.brandCheck(this, WebSocket) + + // The url getter steps are to return this's url, serialized. + return URLSerializer(this[kWebSocketURL]) + } + + get extensions () { + webidl.brandCheck(this, WebSocket) + + return this.#extensions + } + + get protocol () { + webidl.brandCheck(this, WebSocket) + + return this.#protocol + } + + get onopen () { + webidl.brandCheck(this, WebSocket) + + return this.#events.open + } + + set onopen (fn) { + webidl.brandCheck(this, WebSocket) + + if (this.#events.open) { + this.removeEventListener('open', this.#events.open) + } + + if (typeof fn === 'function') { + this.#events.open = fn + this.addEventListener('open', fn) + } else { + this.#events.open = null + } + } + + get onerror () { + webidl.brandCheck(this, WebSocket) + + return this.#events.error + } + + set onerror (fn) { + webidl.brandCheck(this, WebSocket) + + if (this.#events.error) { + this.removeEventListener('error', this.#events.error) + } + + if (typeof fn === 'function') { + this.#events.error = fn + this.addEventListener('error', fn) + } else { + this.#events.error = null + } + } + + get onclose () { + webidl.brandCheck(this, WebSocket) + + return this.#events.close + } + + set onclose (fn) { + webidl.brandCheck(this, WebSocket) + + if (this.#events.close) { + this.removeEventListener('close', this.#events.close) + } + + if (typeof fn === 'function') { + this.#events.close = fn + this.addEventListener('close', fn) + } else { + this.#events.close = null + } + } + + get onmessage () { + webidl.brandCheck(this, WebSocket) + + return this.#events.message + } + + set onmessage (fn) { + webidl.brandCheck(this, WebSocket) + + if (this.#events.message) { + this.removeEventListener('message', this.#events.message) + } + + if (typeof fn === 'function') { + this.#events.message = fn + this.addEventListener('message', fn) + } else { + this.#events.message = null + } + } + + get binaryType () { + webidl.brandCheck(this, WebSocket) + + return this[kBinaryType] + } + + set binaryType (type) { + webidl.brandCheck(this, WebSocket) + + if (type !== 'blob' && type !== 'arraybuffer') { + this[kBinaryType] = 'blob' + } else { + this[kBinaryType] = type + } + } + + /** + * @see https://websockets.spec.whatwg.org/#feedback-from-the-protocol + */ + #onConnectionEstablished (response) { + // processResponse is called when the "response’s header list has been received and initialized." + // once this happens, the connection is open + this[kResponse] = response + + const parser = new ByteParser(this) + parser.on('drain', function onParserDrain () { + this.ws[kResponse].socket.resume() + }) + + response.socket.ws = this + this[kByteParser] = parser + + // 1. Change the ready state to OPEN (1). + this[kReadyState] = states.OPEN + + // 2. Change the extensions attribute’s value to the extensions in use, if + // it is not the null value. + // https://datatracker.ietf.org/doc/html/rfc6455#section-9.1 + const extensions = response.headersList.get('sec-websocket-extensions') + + if (extensions !== null) { + this.#extensions = extensions + } + + // 3. Change the protocol attribute’s value to the subprotocol in use, if + // it is not the null value. + // https://datatracker.ietf.org/doc/html/rfc6455#section-1.9 + const protocol = response.headersList.get('sec-websocket-protocol') + + if (protocol !== null) { + this.#protocol = protocol + } + + // 4. Fire an event named open at the WebSocket object. + fireEvent('open', this) + } +} + +// https://websockets.spec.whatwg.org/#dom-websocket-connecting +WebSocket.CONNECTING = WebSocket.prototype.CONNECTING = states.CONNECTING +// https://websockets.spec.whatwg.org/#dom-websocket-open +WebSocket.OPEN = WebSocket.prototype.OPEN = states.OPEN +// https://websockets.spec.whatwg.org/#dom-websocket-closing +WebSocket.CLOSING = WebSocket.prototype.CLOSING = states.CLOSING +// https://websockets.spec.whatwg.org/#dom-websocket-closed +WebSocket.CLOSED = WebSocket.prototype.CLOSED = states.CLOSED + +Object.defineProperties(WebSocket.prototype, { + CONNECTING: staticPropertyDescriptors, + OPEN: staticPropertyDescriptors, + CLOSING: staticPropertyDescriptors, + CLOSED: staticPropertyDescriptors, + url: kEnumerableProperty, + readyState: kEnumerableProperty, + bufferedAmount: kEnumerableProperty, + onopen: kEnumerableProperty, + onerror: kEnumerableProperty, + onclose: kEnumerableProperty, + close: kEnumerableProperty, + onmessage: kEnumerableProperty, + binaryType: kEnumerableProperty, + send: kEnumerableProperty, + extensions: kEnumerableProperty, + protocol: kEnumerableProperty, + [Symbol.toStringTag]: { + value: 'WebSocket', + writable: false, + enumerable: false, + configurable: true + } +}) + +Object.defineProperties(WebSocket, { + CONNECTING: staticPropertyDescriptors, + OPEN: staticPropertyDescriptors, + CLOSING: staticPropertyDescriptors, + CLOSED: staticPropertyDescriptors +}) + +webidl.converters['sequence'] = webidl.sequenceConverter( + webidl.converters.DOMString +) + +webidl.converters['DOMString or sequence'] = function (V) { + if (webidl.util.Type(V) === 'Object' && Symbol.iterator in V) { + return webidl.converters['sequence'](V) + } + + return webidl.converters.DOMString(V) +} + +// This implements the propsal made in https://github.com/whatwg/websockets/issues/42 +webidl.converters.WebSocketInit = webidl.dictionaryConverter([ + { + key: 'protocols', + converter: webidl.converters['DOMString or sequence'], + get defaultValue () { + return [] + } + }, + { + key: 'dispatcher', + converter: (V) => V, + get defaultValue () { + return getGlobalDispatcher() + } + }, + { + key: 'headers', + converter: webidl.nullableConverter(webidl.converters.HeadersInit) + } +]) + +webidl.converters['DOMString or sequence or WebSocketInit'] = function (V) { + if (webidl.util.Type(V) === 'Object' && !(Symbol.iterator in V)) { + return webidl.converters.WebSocketInit(V) + } + + return { protocols: webidl.converters['DOMString or sequence'](V) } +} + +webidl.converters.WebSocketSendData = function (V) { + if (webidl.util.Type(V) === 'Object') { + if (isBlobLike(V)) { + return webidl.converters.Blob(V, { strict: false }) + } + + if (ArrayBuffer.isView(V) || types.isAnyArrayBuffer(V)) { + return webidl.converters.BufferSource(V) + } + } + + return webidl.converters.USVString(V) +} + +module.exports = { + WebSocket +} + + +/***/ }), + +/***/ 6328: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +Object.defineProperty(exports, "v1", ({ + enumerable: true, + get: function () { + return _v.default; + } +})); +Object.defineProperty(exports, "v3", ({ + enumerable: true, + get: function () { + return _v2.default; + } +})); +Object.defineProperty(exports, "v4", ({ + enumerable: true, + get: function () { + return _v3.default; + } +})); +Object.defineProperty(exports, "v5", ({ + enumerable: true, + get: function () { + return _v4.default; + } +})); +Object.defineProperty(exports, "NIL", ({ + enumerable: true, + get: function () { + return _nil.default; + } +})); +Object.defineProperty(exports, "version", ({ + enumerable: true, + get: function () { + return _version.default; + } +})); +Object.defineProperty(exports, "validate", ({ + enumerable: true, + get: function () { + return _validate.default; + } +})); +Object.defineProperty(exports, "stringify", ({ + enumerable: true, + get: function () { + return _stringify.default; + } +})); +Object.defineProperty(exports, "parse", ({ + enumerable: true, + get: function () { + return _parse.default; + } +})); + +var _v = _interopRequireDefault(__nccwpck_require__(4962)); + +var _v2 = _interopRequireDefault(__nccwpck_require__(541)); + +var _v3 = _interopRequireDefault(__nccwpck_require__(2027)); + +var _v4 = _interopRequireDefault(__nccwpck_require__(826)); + +var _nil = _interopRequireDefault(__nccwpck_require__(1248)); + +var _version = _interopRequireDefault(__nccwpck_require__(1912)); + +var _validate = _interopRequireDefault(__nccwpck_require__(1064)); + +var _stringify = _interopRequireDefault(__nccwpck_require__(2250)); + +var _parse = _interopRequireDefault(__nccwpck_require__(8759)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/***/ }), + +/***/ 4156: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _crypto = _interopRequireDefault(__nccwpck_require__(6113)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function md5(bytes) { + if (Array.isArray(bytes)) { + bytes = Buffer.from(bytes); + } else if (typeof bytes === 'string') { + bytes = Buffer.from(bytes, 'utf8'); + } + + return _crypto.default.createHash('md5').update(bytes).digest(); +} + +var _default = md5; +exports["default"] = _default; + +/***/ }), + +/***/ 1248: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; +var _default = '00000000-0000-0000-0000-000000000000'; +exports["default"] = _default; + +/***/ }), + +/***/ 8759: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _validate = _interopRequireDefault(__nccwpck_require__(1064)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function parse(uuid) { + if (!(0, _validate.default)(uuid)) { + throw TypeError('Invalid UUID'); + } + + let v; + const arr = new Uint8Array(16); // Parse ########-....-....-....-............ + + arr[0] = (v = parseInt(uuid.slice(0, 8), 16)) >>> 24; + arr[1] = v >>> 16 & 0xff; + arr[2] = v >>> 8 & 0xff; + arr[3] = v & 0xff; // Parse ........-####-....-....-............ + + arr[4] = (v = parseInt(uuid.slice(9, 13), 16)) >>> 8; + arr[5] = v & 0xff; // Parse ........-....-####-....-............ + + arr[6] = (v = parseInt(uuid.slice(14, 18), 16)) >>> 8; + arr[7] = v & 0xff; // Parse ........-....-....-####-............ + + arr[8] = (v = parseInt(uuid.slice(19, 23), 16)) >>> 8; + arr[9] = v & 0xff; // Parse ........-....-....-....-############ + // (Use "/" to avoid 32-bit truncation when bit-shifting high-order bytes) + + arr[10] = (v = parseInt(uuid.slice(24, 36), 16)) / 0x10000000000 & 0xff; + arr[11] = v / 0x100000000 & 0xff; + arr[12] = v >>> 24 & 0xff; + arr[13] = v >>> 16 & 0xff; + arr[14] = v >>> 8 & 0xff; + arr[15] = v & 0xff; + return arr; +} + +var _default = parse; +exports["default"] = _default; + +/***/ }), + +/***/ 3700: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; +var _default = /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i; +exports["default"] = _default; + +/***/ }), + +/***/ 8475: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = rng; + +var _crypto = _interopRequireDefault(__nccwpck_require__(6113)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const rnds8Pool = new Uint8Array(256); // # of random values to pre-allocate + +let poolPtr = rnds8Pool.length; + +function rng() { + if (poolPtr > rnds8Pool.length - 16) { + _crypto.default.randomFillSync(rnds8Pool); + + poolPtr = 0; + } + + return rnds8Pool.slice(poolPtr, poolPtr += 16); +} + +/***/ }), + +/***/ 402: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _crypto = _interopRequireDefault(__nccwpck_require__(6113)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function sha1(bytes) { + if (Array.isArray(bytes)) { + bytes = Buffer.from(bytes); + } else if (typeof bytes === 'string') { + bytes = Buffer.from(bytes, 'utf8'); + } + + return _crypto.default.createHash('sha1').update(bytes).digest(); +} + +var _default = sha1; +exports["default"] = _default; + +/***/ }), + +/***/ 2250: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _validate = _interopRequireDefault(__nccwpck_require__(1064)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Convert array of 16 byte values to UUID string format of the form: + * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX + */ +const byteToHex = []; + +for (let i = 0; i < 256; ++i) { + byteToHex.push((i + 0x100).toString(16).substr(1)); +} + +function stringify(arr, offset = 0) { + // Note: Be careful editing this code! It's been tuned for performance + // and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434 + const uuid = (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase(); // Consistency check for valid UUID. If this throws, it's likely due to one + // of the following: + // - One or more input array values don't map to a hex octet (leading to + // "undefined" in the uuid) + // - Invalid input values for the RFC `version` or `variant` fields + + if (!(0, _validate.default)(uuid)) { + throw TypeError('Stringified UUID is invalid'); + } + + return uuid; +} + +var _default = stringify; +exports["default"] = _default; + +/***/ }), + +/***/ 4962: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _rng = _interopRequireDefault(__nccwpck_require__(8475)); + +var _stringify = _interopRequireDefault(__nccwpck_require__(2250)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// **`v1()` - Generate time-based UUID** +// +// Inspired by https://github.com/LiosK/UUID.js +// and http://docs.python.org/library/uuid.html +let _nodeId; + +let _clockseq; // Previous uuid creation time + + +let _lastMSecs = 0; +let _lastNSecs = 0; // See https://github.com/uuidjs/uuid for API details + +function v1(options, buf, offset) { + let i = buf && offset || 0; + const b = buf || new Array(16); + options = options || {}; + let node = options.node || _nodeId; + let clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq; // node and clockseq need to be initialized to random values if they're not + // specified. We do this lazily to minimize issues related to insufficient + // system entropy. See #189 + + if (node == null || clockseq == null) { + const seedBytes = options.random || (options.rng || _rng.default)(); + + if (node == null) { + // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1) + node = _nodeId = [seedBytes[0] | 0x01, seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5]]; + } + + if (clockseq == null) { + // Per 4.2.2, randomize (14 bit) clockseq + clockseq = _clockseq = (seedBytes[6] << 8 | seedBytes[7]) & 0x3fff; + } + } // UUID timestamps are 100 nano-second units since the Gregorian epoch, + // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so + // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs' + // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00. + + + let msecs = options.msecs !== undefined ? options.msecs : Date.now(); // Per 4.2.1.2, use count of uuid's generated during the current clock + // cycle to simulate higher resolution clock + + let nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1; // Time since last uuid creation (in msecs) + + const dt = msecs - _lastMSecs + (nsecs - _lastNSecs) / 10000; // Per 4.2.1.2, Bump clockseq on clock regression + + if (dt < 0 && options.clockseq === undefined) { + clockseq = clockseq + 1 & 0x3fff; + } // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new + // time interval + + + if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) { + nsecs = 0; + } // Per 4.2.1.2 Throw error if too many uuids are requested + + + if (nsecs >= 10000) { + throw new Error("uuid.v1(): Can't create more than 10M uuids/sec"); + } + + _lastMSecs = msecs; + _lastNSecs = nsecs; + _clockseq = clockseq; // Per 4.1.4 - Convert from unix epoch to Gregorian epoch + + msecs += 12219292800000; // `time_low` + + const tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000; + b[i++] = tl >>> 24 & 0xff; + b[i++] = tl >>> 16 & 0xff; + b[i++] = tl >>> 8 & 0xff; + b[i++] = tl & 0xff; // `time_mid` + + const tmh = msecs / 0x100000000 * 10000 & 0xfffffff; + b[i++] = tmh >>> 8 & 0xff; + b[i++] = tmh & 0xff; // `time_high_and_version` + + b[i++] = tmh >>> 24 & 0xf | 0x10; // include version + + b[i++] = tmh >>> 16 & 0xff; // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant) + + b[i++] = clockseq >>> 8 | 0x80; // `clock_seq_low` + + b[i++] = clockseq & 0xff; // `node` + + for (let n = 0; n < 6; ++n) { + b[i + n] = node[n]; + } + + return buf || (0, _stringify.default)(b); +} + +var _default = v1; +exports["default"] = _default; + +/***/ }), + +/***/ 541: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _v = _interopRequireDefault(__nccwpck_require__(3339)); + +var _md = _interopRequireDefault(__nccwpck_require__(4156)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const v3 = (0, _v.default)('v3', 0x30, _md.default); +var _default = v3; +exports["default"] = _default; + +/***/ }), + +/***/ 3339: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = _default; +exports.URL = exports.DNS = void 0; + +var _stringify = _interopRequireDefault(__nccwpck_require__(2250)); + +var _parse = _interopRequireDefault(__nccwpck_require__(8759)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function stringToBytes(str) { + str = unescape(encodeURIComponent(str)); // UTF8 escape + + const bytes = []; + + for (let i = 0; i < str.length; ++i) { + bytes.push(str.charCodeAt(i)); + } + + return bytes; +} + +const DNS = '6ba7b810-9dad-11d1-80b4-00c04fd430c8'; +exports.DNS = DNS; +const URL = '6ba7b811-9dad-11d1-80b4-00c04fd430c8'; +exports.URL = URL; + +function _default(name, version, hashfunc) { + function generateUUID(value, namespace, buf, offset) { + if (typeof value === 'string') { + value = stringToBytes(value); + } + + if (typeof namespace === 'string') { + namespace = (0, _parse.default)(namespace); + } + + if (namespace.length !== 16) { + throw TypeError('Namespace must be array-like (16 iterable integer values, 0-255)'); + } // Compute hash of namespace and value, Per 4.3 + // Future: Use spread syntax when supported on all platforms, e.g. `bytes = + // hashfunc([...namespace, ... value])` + + + let bytes = new Uint8Array(16 + value.length); + bytes.set(namespace); + bytes.set(value, namespace.length); + bytes = hashfunc(bytes); + bytes[6] = bytes[6] & 0x0f | version; + bytes[8] = bytes[8] & 0x3f | 0x80; + + if (buf) { + offset = offset || 0; + + for (let i = 0; i < 16; ++i) { + buf[offset + i] = bytes[i]; + } + + return buf; + } + + return (0, _stringify.default)(bytes); + } // Function#name is not settable on some platforms (#270) + + + try { + generateUUID.name = name; // eslint-disable-next-line no-empty + } catch (err) {} // For CommonJS default export support + + + generateUUID.DNS = DNS; + generateUUID.URL = URL; + return generateUUID; +} + +/***/ }), + +/***/ 2027: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _rng = _interopRequireDefault(__nccwpck_require__(8475)); + +var _stringify = _interopRequireDefault(__nccwpck_require__(2250)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function v4(options, buf, offset) { + options = options || {}; + + const rnds = options.random || (options.rng || _rng.default)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` + + + rnds[6] = rnds[6] & 0x0f | 0x40; + rnds[8] = rnds[8] & 0x3f | 0x80; // Copy bytes to buffer, if provided + + if (buf) { + offset = offset || 0; + + for (let i = 0; i < 16; ++i) { + buf[offset + i] = rnds[i]; + } + + return buf; + } + + return (0, _stringify.default)(rnds); +} + +var _default = v4; +exports["default"] = _default; + +/***/ }), + +/***/ 826: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _v = _interopRequireDefault(__nccwpck_require__(3339)); + +var _sha = _interopRequireDefault(__nccwpck_require__(402)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const v5 = (0, _v.default)('v5', 0x50, _sha.default); +var _default = v5; +exports["default"] = _default; + +/***/ }), + +/***/ 1064: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _regex = _interopRequireDefault(__nccwpck_require__(3700)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function validate(uuid) { + return typeof uuid === 'string' && _regex.default.test(uuid); +} + +var _default = validate; +exports["default"] = _default; + +/***/ }), + +/***/ 1912: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _validate = _interopRequireDefault(__nccwpck_require__(1064)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function version(uuid) { + if (!(0, _validate.default)(uuid)) { + throw TypeError('Invalid UUID'); + } + + return parseInt(uuid.substr(14, 1), 16); +} + +var _default = version; +exports["default"] = _default; + +/***/ }), + +/***/ 9254: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +const steps_1 = __nccwpck_require__(9183); +const inputs_1 = __nccwpck_require__(2117); +const state_1 = __nccwpck_require__(5034); +const core = __importStar(__nccwpck_require__(3949)); +const types_1 = __nccwpck_require__(2106); +/** + * Runs the action + */ +async function run() { + const inputs = await (0, inputs_1.getInputs)(); + for (const step of inputs.steps) { + core.info(`Running step: ${step}`); + switch (step) { + case types_1.ActionStep.BUILD: { + await (0, steps_1.buildStep)(); + break; + } + case types_1.ActionStep.PUSH: { + await (0, steps_1.pushStep)(); + break; + } + case types_1.ActionStep.DEPLOY: { + await (0, steps_1.deployStep)(); + break; + } + default: + core.error(`Unknown action step: ${step}!`); + throw new Error(`Unknown action step: ${step}!`); + } + } +} +/** + * Runs the post action cleanup step + */ +async function post() { } +setImmediate(async () => { + if (!state_1.IS_POST) { + await run(); + } + else { + await post(); + } +}); + + +/***/ }), + +/***/ 2117: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getInputs = void 0; +const types_1 = __nccwpck_require__(2106); +const core = __importStar(__nccwpck_require__(3949)); +const utils_1 = __nccwpck_require__(7407); +const getBuildInputs = () => { + const tag = core.getInput('tag'); + return { + tag, + images: [], + }; +}; +const getPushInputs = () => { + const username = process.env.DOCKERHUB_USERNAME; + if (!username) { + core.error('No DockerHub username found in DOCKERHUB_USERNAME environment variable!'); + throw new Error('No DockerHub username found in DOCKERHUB_USERNAME environment variable!'); + } + const password = process.env.DOCKERHUB_PASSWORD; + if (!password) { + core.error('No DockerHub password found in DOCKERHUB_PASSWORD environment variable!'); + throw new Error('No DockerHub password found in DOCKERHUB_PASSWORD environment variable!'); + } + return { + dockerUsername: username, + dockerPassword: password, + }; +}; +const getDeployIUputs = () => { + const services = getInputList('services'); + const cloudEnvironment = process.env['CLOUD_ENV']; + if (!cloudEnvironment) { + core.error('No CLOUD_ENV environment variable found!'); + throw new Error('No CLOUD_ENV environment variable found!'); + } + const eksClusterName = process.env.CROWD_CLUSTER; + if (!eksClusterName) { + core.error('No CROWD_CLUSTER environment variable found!'); + throw new Error('No CROWD_CLUSTER environment variable found!'); + } + const awsRoleArn = process.env.CROWD_ROLE_ARN; + if (!awsRoleArn) { + core.error('No CROWD_ROLE_ARN environment variable found!'); + throw new Error('No CROWD_ROLE_ARN environment variable found!'); + } + const awsAccessKeyId = process.env.AWS_ACCESS_KEY_ID; + if (!awsAccessKeyId) { + core.error('No AWS_ACCESS_KEY_ID environment variable found!'); + throw new Error('No AWS_ACCESS_KEY_ID environment variable found!'); + } + const awsSecretAccessKey = process.env.AWS_SECRET_ACCESS_KEY; + if (!awsSecretAccessKey) { + core.error('No AWS_SECRET_ACCESS_KEY environment variable found!'); + throw new Error('No AWS_SECRET_ACCESS_KEY environment variable found!'); + } + const awsRegion = process.env.AWS_REGION; + if (!awsRegion) { + core.error('No AWS_REGION environment variable found!'); + throw new Error('No AWS_REGION environment variable found!'); + } + return { + services, + cloudEnvironment, + eksClusterName, + awsRoleArn, + awsAccessKeyId, + awsSecretAccessKey, + awsRegion, + }; +}; +let inputs; +const getInputs = async () => { + if (inputs !== undefined) { + return inputs; + } + const actionSteps = getInputList('steps'); + if (actionSteps.length === 0) { + core.error('No action steps provided!'); + throw new Error('No action steps provided!'); + } + const results = { + steps: actionSteps, + }; + for (const step of actionSteps) { + switch (step) { + case types_1.ActionStep.BUILD: + results[types_1.ActionStep.BUILD] = getBuildInputs(); + break; + case types_1.ActionStep.PUSH: + results[types_1.ActionStep.PUSH] = getPushInputs(); + break; + case types_1.ActionStep.DEPLOY: + results[types_1.ActionStep.DEPLOY] = getDeployIUputs(); + break; + default: + core.error(`Unknown action step: ${step}!`); + throw new Error(`Unknown action step: ${step}!`); + } + } + if (results[types_1.ActionStep.BUILD] !== undefined) { + if (results[types_1.ActionStep.BUILD].images.length === 0 && results[types_1.ActionStep.DEPLOY] !== undefined) { + // calculate images from services + const buildDefinitions = await (0, utils_1.getBuilderDefinitions)(); + const images = []; + for (const service of results[types_1.ActionStep.DEPLOY].services) { + const definition = buildDefinitions.find((d) => d.services.includes(service)); + if (definition === undefined) { + core.error(`No builder definition found for service: ${service}!`); + throw new Error(`No builder definition found for service: ${service}!`); + } + if (!images.includes(definition.imageName)) { + images.push(definition.imageName); + } + } + results[types_1.ActionStep.BUILD].images = images; + } + } + if (results[types_1.ActionStep.PUSH] !== undefined && results[types_1.ActionStep.BUILD] === undefined) { + core.error('Push step provided without build step!'); + throw new Error('Push step provided without build step!'); + } + if (results[types_1.ActionStep.DEPLOY] !== undefined && results[types_1.ActionStep.PUSH] === undefined) { + core.error('Deploy step provided without push step!'); + throw new Error('Deploy step provided without push step!'); + } + inputs = results; + return results; +}; +exports.getInputs = getInputs; +const getInputList = (name) => { + const items = core.getInput(name); + return items + .split(' ') + .map((s) => s.trim()) + .filter((s) => s.length > 0); +}; + + +/***/ }), + +/***/ 5034: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.IS_POST = void 0; +const core = __importStar(__nccwpck_require__(3949)); +exports.IS_POST = !!process.env['STATE_isPost']; +if (!exports.IS_POST) { + core.saveState('isPost', 'true'); +} + + +/***/ }), + +/***/ 9183: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.deployStep = exports.pushStep = exports.buildStep = void 0; +const inputs_1 = __nccwpck_require__(2117); +const types_1 = __nccwpck_require__(2106); +const core = __importStar(__nccwpck_require__(3949)); +const exec = __importStar(__nccwpck_require__(7912)); +const utils_1 = __nccwpck_require__(7407); +const imageTagMap = new Map(); +const buildStep = async () => { + const inputs = await (0, inputs_1.getInputs)(); + if (inputs[types_1.ActionStep.BUILD] === undefined) { + core.error('No build inputs provided!'); + throw new Error('No build inputs provided!'); + } + const { images, tag } = inputs[types_1.ActionStep.BUILD]; + if (images.length === 0) { + core.error('No images provided!'); + throw new Error('No images provided!'); + } + if (!tag) { + core.error('No tag provided!'); + throw new Error('No tag provided!'); + } + const timestamp = Math.floor(Date.now() / 1000); + const actualTag = `${tag}.${timestamp}`; + const alreadyBuilt = []; + for (const image of images) { + if (alreadyBuilt.includes(image)) { + core.info(`Skipping already built image: ${image}:${actualTag}`); + continue; + } + core.info(`Building image: ${image}:${actualTag}`); + const exitCode = await exec.exec('bash', ['cli', 'build', image, actualTag], { + cwd: './scripts', + }); + if (exitCode !== 0) { + core.error(`Failed to build image: ${image}:${actualTag}`); + } + else { + alreadyBuilt.push(image); + imageTagMap.set(image, actualTag); + } + } +}; +exports.buildStep = buildStep; +const pushStep = async () => { + var _a, _b; + const inputs = await (0, inputs_1.getInputs)(); + const images = (_b = (_a = inputs[types_1.ActionStep.BUILD]) === null || _a === void 0 ? void 0 : _a.images) !== null && _b !== void 0 ? _b : []; + const pushInput = inputs[types_1.ActionStep.PUSH]; + if (!pushInput) { + core.error('No push inputs provided!'); + throw new Error('No push inputs provided!'); + } + if (images.length === 0) { + core.error('No images provided!'); + throw new Error('No images provided!'); + } + // do a docker login + const exitCode = await exec.exec('docker', [ + 'login', + '--username', + pushInput.dockerUsername, + '--password', + pushInput.dockerPassword, + ]); + if (exitCode !== 0) { + core.error('Failed to login to docker!'); + throw new Error('Failed to login to docker!'); + } + // now push the images + const alreadyPushed = []; + for (const image of images) { + if (alreadyPushed.includes(image)) { + core.info(`Skipping already pushed image: ${image}`); + continue; + } + if (!imageTagMap.has(image)) { + core.warning(`No tag found for image: ${image} - image wasn't built successfully!`); + continue; + } + const tag = imageTagMap.get(image); + core.info(`Pushing image: ${image}:${tag}!`); + const exitCode = await exec.exec('bash', ['cli', 'push', image, tag], { + cwd: './scripts', + }); + if (exitCode !== 0) { + core.error(`Failed to push image: ${image}:${tag}`); + imageTagMap.delete(image); + } + else { + alreadyPushed.push(image); + } + } +}; +exports.pushStep = pushStep; +const deployStep = async () => { + const inputs = await (0, inputs_1.getInputs)(); + const deployInput = inputs[types_1.ActionStep.DEPLOY]; + if (!deployInput) { + core.error('No deploy inputs provided!'); + throw new Error('No deploy inputs provided!'); + } + if (deployInput.services.length === 0) { + core.warning('No services specified for deploy!'); + return; + } + // check if any images failed to build + const builderDefinitions = await (0, utils_1.getBuilderDefinitions)(); + const servicesToDeploy = []; + for (const service of deployInput.services) { + const builderDef = builderDefinitions.find((b) => b.services.includes(service)); + if (!builderDef) { + core.error(`No builder definition found for service: ${service}`); + throw new Error(`No builder definition found for service: ${service}`); + } + if (!imageTagMap.has(builderDef.imageName)) { + core.error(`No tag found for image: ${builderDef.imageName} - image wasn't built successfully!`); + throw new Error(`No tag found for image: ${builderDef.imageName} - image wasn't built successfully!`); + } + const tag = imageTagMap.get(builderDef.imageName); + servicesToDeploy.push({ + service, + tag, + builderDef, + }); + } + const env = { + AWS_ACCESS_KEY_ID: deployInput.awsAccessKeyId, + AWS_SECRET_ACCESS_KEY: deployInput.awsSecretAccessKey, + AWS_REGION: deployInput.awsRegion, + }; + let exitCode = await exec.exec('aws', [ + 'eks', + 'update-kubeconfig', + '--name', + deployInput.eksClusterName, + '--role-arn', + deployInput.awsRoleArn, + ], { + env, + }); + if (exitCode !== 0) { + core.error('Failed to update kubeconfig!'); + throw new Error('Failed to update kubeconfig!'); + } + let failed = []; + for (const serviceDef of servicesToDeploy) { + const tag = serviceDef.tag; + const service = serviceDef.service; + const prioritized = serviceDef.builderDef.prioritizedServices.includes(service); + const servicesToUpdate = []; + if (prioritized) { + switch (deployInput.cloudEnvironment) { + case types_1.CloudEnvironment.PRODUCTION: { + servicesToUpdate.push(...[`${service}-system`, `${service}-normal`, `${service}-high`, `${service}-urgent`]); + break; + } + case types_1.CloudEnvironment.LF_PRODUCTION: { + servicesToUpdate.push(...[`${service}-system`, `${service}-normal`, `${service}-high`]); + break; + } + case types_1.CloudEnvironment.LF_STAGING: + case types_1.CloudEnvironment.STAGING: { + servicesToUpdate.push(`${service}-normal`); + break; + } + default: + core.error(`Unknown cloud environment: ${deployInput.cloudEnvironment}`); + throw new Error(`Unknown cloud environment: ${deployInput.cloudEnvironment}`); + } + } + else { + servicesToUpdate.push(service); + } + core.info(`Deploying service: ${service} with image: ${serviceDef.builderDef.dockerRepository}:${tag} to deployments: ${servicesToUpdate.join(', ')}`); + for (const toDeploy of servicesToUpdate) { + exitCode = await exec.exec('kubectl', [ + 'set', + 'image', + `deployments/${toDeploy}-dpl`, + `${toDeploy}=${serviceDef.builderDef.dockerRepository}:${tag}`, + ]); + if (exitCode !== 0) { + core.error(`Failed to deploy service: ${service} to deployment: ${toDeploy}`); + if (!failed.includes(service)) { + failed.push(service); + } + } + } + } + if (failed.length > 0) { + core.error(`Failed to deploy services: ${failed.join(', ')}`); + throw new Error(`Failed to deploy services: ${failed.join(', ')}`); + } +}; +exports.deployStep = deployStep; + + +/***/ }), + +/***/ 2106: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.CloudEnvironment = exports.ActionStep = void 0; +var ActionStep; +(function (ActionStep) { + ActionStep["BUILD"] = "build"; + ActionStep["PUSH"] = "push"; + ActionStep["DEPLOY"] = "deploy"; +})(ActionStep || (exports.ActionStep = ActionStep = {})); +var CloudEnvironment; +(function (CloudEnvironment) { + CloudEnvironment["PRODUCTION"] = "production"; + CloudEnvironment["STAGING"] = "staging"; + CloudEnvironment["LF_PRODUCTION"] = "lf-production"; + CloudEnvironment["LF_STAGING"] = "lf-staging"; +})(CloudEnvironment || (exports.CloudEnvironment = CloudEnvironment = {})); + + +/***/ }), + +/***/ 7407: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getBuilderDefinitions = void 0; +const dotenv_1 = __importDefault(__nccwpck_require__(8248)); +const fs_1 = __importDefault(__nccwpck_require__(7147)); +let definitions; +const getBuilderDefinitions = async () => { + if (definitions !== undefined) { + return definitions; + } + const results = []; + const files = fs_1.default.readdirSync('./scripts/builders'); + for (const result of files) { + if (result.endsWith('.env')) { + const content = fs_1.default.readFileSync(`./scripts/builders/${result}`, 'utf-8'); + const parsed = dotenv_1.default.parse(content); + const imageName = result.split('.env')[0]; + const dockerRepository = parsed.REPO; + let services = []; + if (parsed.SERVICES !== undefined) { + services = parsed.SERVICES.split(' ') + .map((s) => s.trim()) + .filter((s) => s.length > 0); + } + let prioritizedServices = []; + if (parsed.PRIORITIZED !== undefined) { + prioritizedServices = parsed.PRIORITIZED.split(' ') + .map((s) => s.trim()) + .filter((s) => s.length > 0); + } + results.push({ + imageName, + dockerRepository, + services, + prioritizedServices, + }); + } + } + definitions = results; + return results; +}; +exports.getBuilderDefinitions = getBuilderDefinitions; + + +/***/ }), + +/***/ 9491: +/***/ ((module) => { + +"use strict"; +module.exports = require("assert"); + +/***/ }), + +/***/ 852: +/***/ ((module) => { + +"use strict"; +module.exports = require("async_hooks"); + +/***/ }), + +/***/ 4300: +/***/ ((module) => { + +"use strict"; +module.exports = require("buffer"); + +/***/ }), + +/***/ 2081: +/***/ ((module) => { + +"use strict"; +module.exports = require("child_process"); + +/***/ }), + +/***/ 6206: +/***/ ((module) => { + +"use strict"; +module.exports = require("console"); + +/***/ }), + +/***/ 6113: +/***/ ((module) => { + +"use strict"; +module.exports = require("crypto"); + +/***/ }), + +/***/ 7643: +/***/ ((module) => { + +"use strict"; +module.exports = require("diagnostics_channel"); + +/***/ }), + +/***/ 2361: +/***/ ((module) => { + +"use strict"; +module.exports = require("events"); + +/***/ }), + +/***/ 7147: +/***/ ((module) => { + +"use strict"; +module.exports = require("fs"); + +/***/ }), + +/***/ 3685: +/***/ ((module) => { + +"use strict"; +module.exports = require("http"); + +/***/ }), + +/***/ 5158: +/***/ ((module) => { + +"use strict"; +module.exports = require("http2"); + +/***/ }), + +/***/ 5687: +/***/ ((module) => { + +"use strict"; +module.exports = require("https"); + +/***/ }), + +/***/ 1808: +/***/ ((module) => { + +"use strict"; +module.exports = require("net"); + +/***/ }), + +/***/ 8061: +/***/ ((module) => { + +"use strict"; +module.exports = require("node:assert"); + +/***/ }), + +/***/ 5673: +/***/ ((module) => { + +"use strict"; +module.exports = require("node:events"); + +/***/ }), + +/***/ 4492: +/***/ ((module) => { + +"use strict"; +module.exports = require("node:stream"); + +/***/ }), + +/***/ 7261: +/***/ ((module) => { + +"use strict"; +module.exports = require("node:util"); + +/***/ }), + +/***/ 2037: +/***/ ((module) => { + +"use strict"; +module.exports = require("os"); + +/***/ }), + +/***/ 1017: +/***/ ((module) => { + +"use strict"; +module.exports = require("path"); + +/***/ }), + +/***/ 4074: +/***/ ((module) => { + +"use strict"; +module.exports = require("perf_hooks"); + +/***/ }), + +/***/ 3477: +/***/ ((module) => { + +"use strict"; +module.exports = require("querystring"); + +/***/ }), + +/***/ 2781: +/***/ ((module) => { + +"use strict"; +module.exports = require("stream"); + +/***/ }), + +/***/ 5356: +/***/ ((module) => { + +"use strict"; +module.exports = require("stream/web"); + +/***/ }), + +/***/ 1576: +/***/ ((module) => { + +"use strict"; +module.exports = require("string_decoder"); + +/***/ }), + +/***/ 9512: +/***/ ((module) => { + +"use strict"; +module.exports = require("timers"); + +/***/ }), + +/***/ 4404: +/***/ ((module) => { + +"use strict"; +module.exports = require("tls"); + +/***/ }), + +/***/ 7310: +/***/ ((module) => { + +"use strict"; +module.exports = require("url"); + +/***/ }), + +/***/ 3837: +/***/ ((module) => { + +"use strict"; +module.exports = require("util"); + +/***/ }), + +/***/ 9830: +/***/ ((module) => { + +"use strict"; +module.exports = require("util/types"); + +/***/ }), + +/***/ 1267: +/***/ ((module) => { + +"use strict"; +module.exports = require("worker_threads"); + +/***/ }), + +/***/ 9796: +/***/ ((module) => { + +"use strict"; +module.exports = require("zlib"); + +/***/ }), + +/***/ 7826: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const WritableStream = (__nccwpck_require__(4492).Writable) +const inherits = (__nccwpck_require__(7261).inherits) + +const StreamSearch = __nccwpck_require__(1718) + +const PartStream = __nccwpck_require__(7119) +const HeaderParser = __nccwpck_require__(1847) + +const DASH = 45 +const B_ONEDASH = Buffer.from('-') +const B_CRLF = Buffer.from('\r\n') +const EMPTY_FN = function () {} + +function Dicer (cfg) { + if (!(this instanceof Dicer)) { return new Dicer(cfg) } + WritableStream.call(this, cfg) + + if (!cfg || (!cfg.headerFirst && typeof cfg.boundary !== 'string')) { throw new TypeError('Boundary required') } + + if (typeof cfg.boundary === 'string') { this.setBoundary(cfg.boundary) } else { this._bparser = undefined } + + this._headerFirst = cfg.headerFirst + + this._dashes = 0 + this._parts = 0 + this._finished = false + this._realFinish = false + this._isPreamble = true + this._justMatched = false + this._firstWrite = true + this._inHeader = true + this._part = undefined + this._cb = undefined + this._ignoreData = false + this._partOpts = { highWaterMark: cfg.partHwm } + this._pause = false + + const self = this + this._hparser = new HeaderParser(cfg) + this._hparser.on('header', function (header) { + self._inHeader = false + self._part.emit('header', header) + }) +} +inherits(Dicer, WritableStream) + +Dicer.prototype.emit = function (ev) { + if (ev === 'finish' && !this._realFinish) { + if (!this._finished) { + const self = this + process.nextTick(function () { + self.emit('error', new Error('Unexpected end of multipart data')) + if (self._part && !self._ignoreData) { + const type = (self._isPreamble ? 'Preamble' : 'Part') + self._part.emit('error', new Error(type + ' terminated early due to unexpected end of multipart data')) + self._part.push(null) + process.nextTick(function () { + self._realFinish = true + self.emit('finish') + self._realFinish = false + }) + return + } + self._realFinish = true + self.emit('finish') + self._realFinish = false + }) + } + } else { WritableStream.prototype.emit.apply(this, arguments) } +} + +Dicer.prototype._write = function (data, encoding, cb) { + // ignore unexpected data (e.g. extra trailer data after finished) + if (!this._hparser && !this._bparser) { return cb() } + + if (this._headerFirst && this._isPreamble) { + if (!this._part) { + this._part = new PartStream(this._partOpts) + if (this._events.preamble) { this.emit('preamble', this._part) } else { this._ignore() } + } + const r = this._hparser.push(data) + if (!this._inHeader && r !== undefined && r < data.length) { data = data.slice(r) } else { return cb() } + } + + // allows for "easier" testing + if (this._firstWrite) { + this._bparser.push(B_CRLF) + this._firstWrite = false + } + + this._bparser.push(data) + + if (this._pause) { this._cb = cb } else { cb() } +} + +Dicer.prototype.reset = function () { + this._part = undefined + this._bparser = undefined + this._hparser = undefined +} + +Dicer.prototype.setBoundary = function (boundary) { + const self = this + this._bparser = new StreamSearch('\r\n--' + boundary) + this._bparser.on('info', function (isMatch, data, start, end) { + self._oninfo(isMatch, data, start, end) + }) +} + +Dicer.prototype._ignore = function () { + if (this._part && !this._ignoreData) { + this._ignoreData = true + this._part.on('error', EMPTY_FN) + // we must perform some kind of read on the stream even though we are + // ignoring the data, otherwise node's Readable stream will not emit 'end' + // after pushing null to the stream + this._part.resume() + } +} + +Dicer.prototype._oninfo = function (isMatch, data, start, end) { + let buf; const self = this; let i = 0; let r; let shouldWriteMore = true + + if (!this._part && this._justMatched && data) { + while (this._dashes < 2 && (start + i) < end) { + if (data[start + i] === DASH) { + ++i + ++this._dashes + } else { + if (this._dashes) { buf = B_ONEDASH } + this._dashes = 0 + break + } + } + if (this._dashes === 2) { + if ((start + i) < end && this._events.trailer) { this.emit('trailer', data.slice(start + i, end)) } + this.reset() + this._finished = true + // no more parts will be added + if (self._parts === 0) { + self._realFinish = true + self.emit('finish') + self._realFinish = false + } + } + if (this._dashes) { return } + } + if (this._justMatched) { this._justMatched = false } + if (!this._part) { + this._part = new PartStream(this._partOpts) + this._part._read = function (n) { + self._unpause() + } + if (this._isPreamble && this._events.preamble) { this.emit('preamble', this._part) } else if (this._isPreamble !== true && this._events.part) { this.emit('part', this._part) } else { this._ignore() } + if (!this._isPreamble) { this._inHeader = true } + } + if (data && start < end && !this._ignoreData) { + if (this._isPreamble || !this._inHeader) { + if (buf) { shouldWriteMore = this._part.push(buf) } + shouldWriteMore = this._part.push(data.slice(start, end)) + if (!shouldWriteMore) { this._pause = true } + } else if (!this._isPreamble && this._inHeader) { + if (buf) { this._hparser.push(buf) } + r = this._hparser.push(data.slice(start, end)) + if (!this._inHeader && r !== undefined && r < end) { this._oninfo(false, data, start + r, end) } + } + } + if (isMatch) { + this._hparser.reset() + if (this._isPreamble) { this._isPreamble = false } else { + if (start !== end) { + ++this._parts + this._part.on('end', function () { + if (--self._parts === 0) { + if (self._finished) { + self._realFinish = true + self.emit('finish') + self._realFinish = false + } else { + self._unpause() + } + } + }) + } + } + this._part.push(null) + this._part = undefined + this._ignoreData = false + this._justMatched = true + this._dashes = 0 + } +} + +Dicer.prototype._unpause = function () { + if (!this._pause) { return } + + this._pause = false + if (this._cb) { + const cb = this._cb + this._cb = undefined + cb() + } +} + +module.exports = Dicer + + +/***/ }), + +/***/ 1847: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const EventEmitter = (__nccwpck_require__(5673).EventEmitter) +const inherits = (__nccwpck_require__(7261).inherits) +const getLimit = __nccwpck_require__(8459) + +const StreamSearch = __nccwpck_require__(1718) + +const B_DCRLF = Buffer.from('\r\n\r\n') +const RE_CRLF = /\r\n/g +const RE_HDR = /^([^:]+):[ \t]?([\x00-\xFF]+)?$/ // eslint-disable-line no-control-regex + +function HeaderParser (cfg) { + EventEmitter.call(this) + + cfg = cfg || {} + const self = this + this.nread = 0 + this.maxed = false + this.npairs = 0 + this.maxHeaderPairs = getLimit(cfg, 'maxHeaderPairs', 2000) + this.maxHeaderSize = getLimit(cfg, 'maxHeaderSize', 80 * 1024) + this.buffer = '' + this.header = {} + this.finished = false + this.ss = new StreamSearch(B_DCRLF) + this.ss.on('info', function (isMatch, data, start, end) { + if (data && !self.maxed) { + if (self.nread + end - start >= self.maxHeaderSize) { + end = self.maxHeaderSize - self.nread + start + self.nread = self.maxHeaderSize + self.maxed = true + } else { self.nread += (end - start) } + + self.buffer += data.toString('binary', start, end) + } + if (isMatch) { self._finish() } + }) +} +inherits(HeaderParser, EventEmitter) + +HeaderParser.prototype.push = function (data) { + const r = this.ss.push(data) + if (this.finished) { return r } +} + +HeaderParser.prototype.reset = function () { + this.finished = false + this.buffer = '' + this.header = {} + this.ss.reset() +} + +HeaderParser.prototype._finish = function () { + if (this.buffer) { this._parseHeader() } + this.ss.matches = this.ss.maxMatches + const header = this.header + this.header = {} + this.buffer = '' + this.finished = true + this.nread = this.npairs = 0 + this.maxed = false + this.emit('header', header) +} + +HeaderParser.prototype._parseHeader = function () { + if (this.npairs === this.maxHeaderPairs) { return } + + const lines = this.buffer.split(RE_CRLF) + const len = lines.length + let m, h + + for (var i = 0; i < len; ++i) { // eslint-disable-line no-var + if (lines[i].length === 0) { continue } + if (lines[i][0] === '\t' || lines[i][0] === ' ') { + // folded header content + // RFC2822 says to just remove the CRLF and not the whitespace following + // it, so we follow the RFC and include the leading whitespace ... + if (h) { + this.header[h][this.header[h].length - 1] += lines[i] + continue + } + } + + const posColon = lines[i].indexOf(':') + if ( + posColon === -1 || + posColon === 0 + ) { + return + } + m = RE_HDR.exec(lines[i]) + h = m[1].toLowerCase() + this.header[h] = this.header[h] || [] + this.header[h].push((m[2] || '')) + if (++this.npairs === this.maxHeaderPairs) { break } + } +} + +module.exports = HeaderParser + + +/***/ }), + +/***/ 7119: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const inherits = (__nccwpck_require__(7261).inherits) +const ReadableStream = (__nccwpck_require__(4492).Readable) + +function PartStream (opts) { + ReadableStream.call(this, opts) +} +inherits(PartStream, ReadableStream) + +PartStream.prototype._read = function (n) {} + +module.exports = PartStream + + +/***/ }), + +/***/ 1718: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +/** + * Copyright Brian White. All rights reserved. + * + * @see https://github.com/mscdex/streamsearch + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Based heavily on the Streaming Boyer-Moore-Horspool C++ implementation + * by Hongli Lai at: https://github.com/FooBarWidget/boyer-moore-horspool + */ +const EventEmitter = (__nccwpck_require__(5673).EventEmitter) +const inherits = (__nccwpck_require__(7261).inherits) + +function SBMH (needle) { + if (typeof needle === 'string') { + needle = Buffer.from(needle) + } + + if (!Buffer.isBuffer(needle)) { + throw new TypeError('The needle has to be a String or a Buffer.') + } + + const needleLength = needle.length + + if (needleLength === 0) { + throw new Error('The needle cannot be an empty String/Buffer.') + } + + if (needleLength > 256) { + throw new Error('The needle cannot have a length bigger than 256.') + } + + this.maxMatches = Infinity + this.matches = 0 + + this._occ = new Array(256) + .fill(needleLength) // Initialize occurrence table. + this._lookbehind_size = 0 + this._needle = needle + this._bufpos = 0 + + this._lookbehind = Buffer.alloc(needleLength) + + // Populate occurrence table with analysis of the needle, + // ignoring last letter. + for (var i = 0; i < needleLength - 1; ++i) { // eslint-disable-line no-var + this._occ[needle[i]] = needleLength - 1 - i + } +} +inherits(SBMH, EventEmitter) + +SBMH.prototype.reset = function () { + this._lookbehind_size = 0 + this.matches = 0 + this._bufpos = 0 +} + +SBMH.prototype.push = function (chunk, pos) { + if (!Buffer.isBuffer(chunk)) { + chunk = Buffer.from(chunk, 'binary') + } + const chlen = chunk.length + this._bufpos = pos || 0 + let r + while (r !== chlen && this.matches < this.maxMatches) { r = this._sbmh_feed(chunk) } + return r +} + +SBMH.prototype._sbmh_feed = function (data) { + const len = data.length + const needle = this._needle + const needleLength = needle.length + const lastNeedleChar = needle[needleLength - 1] + + // Positive: points to a position in `data` + // pos == 3 points to data[3] + // Negative: points to a position in the lookbehind buffer + // pos == -2 points to lookbehind[lookbehind_size - 2] + let pos = -this._lookbehind_size + let ch + + if (pos < 0) { + // Lookbehind buffer is not empty. Perform Boyer-Moore-Horspool + // search with character lookup code that considers both the + // lookbehind buffer and the current round's haystack data. + // + // Loop until + // there is a match. + // or until + // we've moved past the position that requires the + // lookbehind buffer. In this case we switch to the + // optimized loop. + // or until + // the character to look at lies outside the haystack. + while (pos < 0 && pos <= len - needleLength) { + ch = this._sbmh_lookup_char(data, pos + needleLength - 1) + + if ( + ch === lastNeedleChar && + this._sbmh_memcmp(data, pos, needleLength - 1) + ) { + this._lookbehind_size = 0 + ++this.matches + this.emit('info', true) + + return (this._bufpos = pos + needleLength) + } + pos += this._occ[ch] + } + + // No match. + + if (pos < 0) { + // There's too few data for Boyer-Moore-Horspool to run, + // so let's use a different algorithm to skip as much as + // we can. + // Forward pos until + // the trailing part of lookbehind + data + // looks like the beginning of the needle + // or until + // pos == 0 + while (pos < 0 && !this._sbmh_memcmp(data, pos, len - pos)) { ++pos } + } + + if (pos >= 0) { + // Discard lookbehind buffer. + this.emit('info', false, this._lookbehind, 0, this._lookbehind_size) + this._lookbehind_size = 0 + } else { + // Cut off part of the lookbehind buffer that has + // been processed and append the entire haystack + // into it. + const bytesToCutOff = this._lookbehind_size + pos + if (bytesToCutOff > 0) { + // The cut off data is guaranteed not to contain the needle. + this.emit('info', false, this._lookbehind, 0, bytesToCutOff) + } + + this._lookbehind.copy(this._lookbehind, 0, bytesToCutOff, + this._lookbehind_size - bytesToCutOff) + this._lookbehind_size -= bytesToCutOff + + data.copy(this._lookbehind, this._lookbehind_size) + this._lookbehind_size += len + + this._bufpos = len + return len + } + } + + pos += (pos >= 0) * this._bufpos + + // Lookbehind buffer is now empty. We only need to check if the + // needle is in the haystack. + if (data.indexOf(needle, pos) !== -1) { + pos = data.indexOf(needle, pos) + ++this.matches + if (pos > 0) { this.emit('info', true, data, this._bufpos, pos) } else { this.emit('info', true) } + + return (this._bufpos = pos + needleLength) + } else { + pos = len - needleLength + } + + // There was no match. If there's trailing haystack data that we cannot + // match yet using the Boyer-Moore-Horspool algorithm (because the trailing + // data is less than the needle size) then match using a modified + // algorithm that starts matching from the beginning instead of the end. + // Whatever trailing data is left after running this algorithm is added to + // the lookbehind buffer. + while ( + pos < len && + ( + data[pos] !== needle[0] || + ( + (Buffer.compare( + data.subarray(pos, pos + len - pos), + needle.subarray(0, len - pos) + ) !== 0) + ) + ) + ) { + ++pos + } + if (pos < len) { + data.copy(this._lookbehind, 0, pos, pos + (len - pos)) + this._lookbehind_size = len - pos + } + + // Everything until pos is guaranteed not to contain needle data. + if (pos > 0) { this.emit('info', false, data, this._bufpos, pos < len ? pos : len) } + + this._bufpos = len + return len +} + +SBMH.prototype._sbmh_lookup_char = function (data, pos) { + return (pos < 0) + ? this._lookbehind[this._lookbehind_size + pos] + : data[pos] +} + +SBMH.prototype._sbmh_memcmp = function (data, pos, len) { + for (var i = 0; i < len; ++i) { // eslint-disable-line no-var + if (this._sbmh_lookup_char(data, pos + i) !== this._needle[i]) { return false } + } + return true +} + +module.exports = SBMH + + +/***/ }), + +/***/ 8162: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const WritableStream = (__nccwpck_require__(4492).Writable) +const { inherits } = __nccwpck_require__(7261) +const Dicer = __nccwpck_require__(7826) + +const MultipartParser = __nccwpck_require__(2698) +const UrlencodedParser = __nccwpck_require__(2875) +const parseParams = __nccwpck_require__(1133) + +function Busboy (opts) { + if (!(this instanceof Busboy)) { return new Busboy(opts) } + + if (typeof opts !== 'object') { + throw new TypeError('Busboy expected an options-Object.') + } + if (typeof opts.headers !== 'object') { + throw new TypeError('Busboy expected an options-Object with headers-attribute.') + } + if (typeof opts.headers['content-type'] !== 'string') { + throw new TypeError('Missing Content-Type-header.') + } + + const { + headers, + ...streamOptions + } = opts + + this.opts = { + autoDestroy: false, + ...streamOptions + } + WritableStream.call(this, this.opts) + + this._done = false + this._parser = this.getParserByHeaders(headers) + this._finished = false +} +inherits(Busboy, WritableStream) + +Busboy.prototype.emit = function (ev) { + if (ev === 'finish') { + if (!this._done) { + this._parser?.end() + return + } else if (this._finished) { + return + } + this._finished = true + } + WritableStream.prototype.emit.apply(this, arguments) +} + +Busboy.prototype.getParserByHeaders = function (headers) { + const parsed = parseParams(headers['content-type']) + + const cfg = { + defCharset: this.opts.defCharset, + fileHwm: this.opts.fileHwm, + headers, + highWaterMark: this.opts.highWaterMark, + isPartAFile: this.opts.isPartAFile, + limits: this.opts.limits, + parsedConType: parsed, + preservePath: this.opts.preservePath + } + + if (MultipartParser.detect.test(parsed[0])) { + return new MultipartParser(this, cfg) + } + if (UrlencodedParser.detect.test(parsed[0])) { + return new UrlencodedParser(this, cfg) + } + throw new Error('Unsupported Content-Type.') +} + +Busboy.prototype._write = function (chunk, encoding, cb) { + this._parser.write(chunk, cb) +} + +module.exports = Busboy +module.exports["default"] = Busboy +module.exports.Busboy = Busboy + +module.exports.Dicer = Dicer + + +/***/ }), + +/***/ 2698: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +// TODO: +// * support 1 nested multipart level +// (see second multipart example here: +// http://www.w3.org/TR/html401/interact/forms.html#didx-multipartform-data) +// * support limits.fieldNameSize +// -- this will require modifications to utils.parseParams + +const { Readable } = __nccwpck_require__(4492) +const { inherits } = __nccwpck_require__(7261) + +const Dicer = __nccwpck_require__(7826) + +const parseParams = __nccwpck_require__(1133) +const decodeText = __nccwpck_require__(2491) +const basename = __nccwpck_require__(299) +const getLimit = __nccwpck_require__(8459) + +const RE_BOUNDARY = /^boundary$/i +const RE_FIELD = /^form-data$/i +const RE_CHARSET = /^charset$/i +const RE_FILENAME = /^filename$/i +const RE_NAME = /^name$/i + +Multipart.detect = /^multipart\/form-data/i +function Multipart (boy, cfg) { + let i + let len + const self = this + let boundary + const limits = cfg.limits + const isPartAFile = cfg.isPartAFile || ((fieldName, contentType, fileName) => (contentType === 'application/octet-stream' || fileName !== undefined)) + const parsedConType = cfg.parsedConType || [] + const defCharset = cfg.defCharset || 'utf8' + const preservePath = cfg.preservePath + const fileOpts = { highWaterMark: cfg.fileHwm } + + for (i = 0, len = parsedConType.length; i < len; ++i) { + if (Array.isArray(parsedConType[i]) && + RE_BOUNDARY.test(parsedConType[i][0])) { + boundary = parsedConType[i][1] + break + } + } + + function checkFinished () { + if (nends === 0 && finished && !boy._done) { + finished = false + self.end() + } + } + + if (typeof boundary !== 'string') { throw new Error('Multipart: Boundary not found') } + + const fieldSizeLimit = getLimit(limits, 'fieldSize', 1 * 1024 * 1024) + const fileSizeLimit = getLimit(limits, 'fileSize', Infinity) + const filesLimit = getLimit(limits, 'files', Infinity) + const fieldsLimit = getLimit(limits, 'fields', Infinity) + const partsLimit = getLimit(limits, 'parts', Infinity) + const headerPairsLimit = getLimit(limits, 'headerPairs', 2000) + const headerSizeLimit = getLimit(limits, 'headerSize', 80 * 1024) + + let nfiles = 0 + let nfields = 0 + let nends = 0 + let curFile + let curField + let finished = false + + this._needDrain = false + this._pause = false + this._cb = undefined + this._nparts = 0 + this._boy = boy + + const parserCfg = { + boundary, + maxHeaderPairs: headerPairsLimit, + maxHeaderSize: headerSizeLimit, + partHwm: fileOpts.highWaterMark, + highWaterMark: cfg.highWaterMark + } + + this.parser = new Dicer(parserCfg) + this.parser.on('drain', function () { + self._needDrain = false + if (self._cb && !self._pause) { + const cb = self._cb + self._cb = undefined + cb() + } + }).on('part', function onPart (part) { + if (++self._nparts > partsLimit) { + self.parser.removeListener('part', onPart) + self.parser.on('part', skipPart) + boy.hitPartsLimit = true + boy.emit('partsLimit') + return skipPart(part) + } + + // hack because streams2 _always_ doesn't emit 'end' until nextTick, so let + // us emit 'end' early since we know the part has ended if we are already + // seeing the next part + if (curField) { + const field = curField + field.emit('end') + field.removeAllListeners('end') + } + + part.on('header', function (header) { + let contype + let fieldname + let parsed + let charset + let encoding + let filename + let nsize = 0 + + if (header['content-type']) { + parsed = parseParams(header['content-type'][0]) + if (parsed[0]) { + contype = parsed[0].toLowerCase() + for (i = 0, len = parsed.length; i < len; ++i) { + if (RE_CHARSET.test(parsed[i][0])) { + charset = parsed[i][1].toLowerCase() + break + } + } + } + } + + if (contype === undefined) { contype = 'text/plain' } + if (charset === undefined) { charset = defCharset } + + if (header['content-disposition']) { + parsed = parseParams(header['content-disposition'][0]) + if (!RE_FIELD.test(parsed[0])) { return skipPart(part) } + for (i = 0, len = parsed.length; i < len; ++i) { + if (RE_NAME.test(parsed[i][0])) { + fieldname = parsed[i][1] + } else if (RE_FILENAME.test(parsed[i][0])) { + filename = parsed[i][1] + if (!preservePath) { filename = basename(filename) } + } + } + } else { return skipPart(part) } + + if (header['content-transfer-encoding']) { encoding = header['content-transfer-encoding'][0].toLowerCase() } else { encoding = '7bit' } + + let onData, + onEnd + + if (isPartAFile(fieldname, contype, filename)) { + // file/binary field + if (nfiles === filesLimit) { + if (!boy.hitFilesLimit) { + boy.hitFilesLimit = true + boy.emit('filesLimit') + } + return skipPart(part) + } + + ++nfiles + + if (!boy._events.file) { + self.parser._ignore() + return + } + + ++nends + const file = new FileStream(fileOpts) + curFile = file + file.on('end', function () { + --nends + self._pause = false + checkFinished() + if (self._cb && !self._needDrain) { + const cb = self._cb + self._cb = undefined + cb() + } + }) + file._read = function (n) { + if (!self._pause) { return } + self._pause = false + if (self._cb && !self._needDrain) { + const cb = self._cb + self._cb = undefined + cb() + } + } + boy.emit('file', fieldname, file, filename, encoding, contype) + + onData = function (data) { + if ((nsize += data.length) > fileSizeLimit) { + const extralen = fileSizeLimit - nsize + data.length + if (extralen > 0) { file.push(data.slice(0, extralen)) } + file.truncated = true + file.bytesRead = fileSizeLimit + part.removeAllListeners('data') + file.emit('limit') + return + } else if (!file.push(data)) { self._pause = true } + + file.bytesRead = nsize + } + + onEnd = function () { + curFile = undefined + file.push(null) + } + } else { + // non-file field + if (nfields === fieldsLimit) { + if (!boy.hitFieldsLimit) { + boy.hitFieldsLimit = true + boy.emit('fieldsLimit') + } + return skipPart(part) + } + + ++nfields + ++nends + let buffer = '' + let truncated = false + curField = part + + onData = function (data) { + if ((nsize += data.length) > fieldSizeLimit) { + const extralen = (fieldSizeLimit - (nsize - data.length)) + buffer += data.toString('binary', 0, extralen) + truncated = true + part.removeAllListeners('data') + } else { buffer += data.toString('binary') } + } + + onEnd = function () { + curField = undefined + if (buffer.length) { buffer = decodeText(buffer, 'binary', charset) } + boy.emit('field', fieldname, buffer, false, truncated, encoding, contype) + --nends + checkFinished() + } + } + + /* As of node@2efe4ab761666 (v0.10.29+/v0.11.14+), busboy had become + broken. Streams2/streams3 is a huge black box of confusion, but + somehow overriding the sync state seems to fix things again (and still + seems to work for previous node versions). + */ + part._readableState.sync = false + + part.on('data', onData) + part.on('end', onEnd) + }).on('error', function (err) { + if (curFile) { curFile.emit('error', err) } + }) + }).on('error', function (err) { + boy.emit('error', err) + }).on('finish', function () { + finished = true + checkFinished() + }) +} + +Multipart.prototype.write = function (chunk, cb) { + const r = this.parser.write(chunk) + if (r && !this._pause) { + cb() + } else { + this._needDrain = !r + this._cb = cb + } +} + +Multipart.prototype.end = function () { + const self = this + + if (self.parser.writable) { + self.parser.end() + } else if (!self._boy._done) { + process.nextTick(function () { + self._boy._done = true + self._boy.emit('finish') + }) + } +} + +function skipPart (part) { + part.resume() +} + +function FileStream (opts) { + Readable.call(this, opts) + + this.bytesRead = 0 + + this.truncated = false +} + +inherits(FileStream, Readable) + +FileStream.prototype._read = function (n) {} + +module.exports = Multipart + + +/***/ }), + +/***/ 2875: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const Decoder = __nccwpck_require__(349) +const decodeText = __nccwpck_require__(2491) +const getLimit = __nccwpck_require__(8459) + +const RE_CHARSET = /^charset$/i + +UrlEncoded.detect = /^application\/x-www-form-urlencoded/i +function UrlEncoded (boy, cfg) { + const limits = cfg.limits + const parsedConType = cfg.parsedConType + this.boy = boy + + this.fieldSizeLimit = getLimit(limits, 'fieldSize', 1 * 1024 * 1024) + this.fieldNameSizeLimit = getLimit(limits, 'fieldNameSize', 100) + this.fieldsLimit = getLimit(limits, 'fields', Infinity) + + let charset + for (var i = 0, len = parsedConType.length; i < len; ++i) { // eslint-disable-line no-var + if (Array.isArray(parsedConType[i]) && + RE_CHARSET.test(parsedConType[i][0])) { + charset = parsedConType[i][1].toLowerCase() + break + } + } + + if (charset === undefined) { charset = cfg.defCharset || 'utf8' } + + this.decoder = new Decoder() + this.charset = charset + this._fields = 0 + this._state = 'key' + this._checkingBytes = true + this._bytesKey = 0 + this._bytesVal = 0 + this._key = '' + this._val = '' + this._keyTrunc = false + this._valTrunc = false + this._hitLimit = false +} + +UrlEncoded.prototype.write = function (data, cb) { + if (this._fields === this.fieldsLimit) { + if (!this.boy.hitFieldsLimit) { + this.boy.hitFieldsLimit = true + this.boy.emit('fieldsLimit') + } + return cb() + } + + let idxeq; let idxamp; let i; let p = 0; const len = data.length + + while (p < len) { + if (this._state === 'key') { + idxeq = idxamp = undefined + for (i = p; i < len; ++i) { + if (!this._checkingBytes) { ++p } + if (data[i] === 0x3D/* = */) { + idxeq = i + break + } else if (data[i] === 0x26/* & */) { + idxamp = i + break + } + if (this._checkingBytes && this._bytesKey === this.fieldNameSizeLimit) { + this._hitLimit = true + break + } else if (this._checkingBytes) { ++this._bytesKey } + } + + if (idxeq !== undefined) { + // key with assignment + if (idxeq > p) { this._key += this.decoder.write(data.toString('binary', p, idxeq)) } + this._state = 'val' + + this._hitLimit = false + this._checkingBytes = true + this._val = '' + this._bytesVal = 0 + this._valTrunc = false + this.decoder.reset() + + p = idxeq + 1 + } else if (idxamp !== undefined) { + // key with no assignment + ++this._fields + let key; const keyTrunc = this._keyTrunc + if (idxamp > p) { key = (this._key += this.decoder.write(data.toString('binary', p, idxamp))) } else { key = this._key } + + this._hitLimit = false + this._checkingBytes = true + this._key = '' + this._bytesKey = 0 + this._keyTrunc = false + this.decoder.reset() + + if (key.length) { + this.boy.emit('field', decodeText(key, 'binary', this.charset), + '', + keyTrunc, + false) + } + + p = idxamp + 1 + if (this._fields === this.fieldsLimit) { return cb() } + } else if (this._hitLimit) { + // we may not have hit the actual limit if there are encoded bytes... + if (i > p) { this._key += this.decoder.write(data.toString('binary', p, i)) } + p = i + if ((this._bytesKey = this._key.length) === this.fieldNameSizeLimit) { + // yep, we actually did hit the limit + this._checkingBytes = false + this._keyTrunc = true + } + } else { + if (p < len) { this._key += this.decoder.write(data.toString('binary', p)) } + p = len + } + } else { + idxamp = undefined + for (i = p; i < len; ++i) { + if (!this._checkingBytes) { ++p } + if (data[i] === 0x26/* & */) { + idxamp = i + break + } + if (this._checkingBytes && this._bytesVal === this.fieldSizeLimit) { + this._hitLimit = true + break + } else if (this._checkingBytes) { ++this._bytesVal } + } + + if (idxamp !== undefined) { + ++this._fields + if (idxamp > p) { this._val += this.decoder.write(data.toString('binary', p, idxamp)) } + this.boy.emit('field', decodeText(this._key, 'binary', this.charset), + decodeText(this._val, 'binary', this.charset), + this._keyTrunc, + this._valTrunc) + this._state = 'key' + + this._hitLimit = false + this._checkingBytes = true + this._key = '' + this._bytesKey = 0 + this._keyTrunc = false + this.decoder.reset() + + p = idxamp + 1 + if (this._fields === this.fieldsLimit) { return cb() } + } else if (this._hitLimit) { + // we may not have hit the actual limit if there are encoded bytes... + if (i > p) { this._val += this.decoder.write(data.toString('binary', p, i)) } + p = i + if ((this._val === '' && this.fieldSizeLimit === 0) || + (this._bytesVal = this._val.length) === this.fieldSizeLimit) { + // yep, we actually did hit the limit + this._checkingBytes = false + this._valTrunc = true + } + } else { + if (p < len) { this._val += this.decoder.write(data.toString('binary', p)) } + p = len + } + } + } + cb() +} + +UrlEncoded.prototype.end = function () { + if (this.boy._done) { return } + + if (this._state === 'key' && this._key.length > 0) { + this.boy.emit('field', decodeText(this._key, 'binary', this.charset), + '', + this._keyTrunc, + false) + } else if (this._state === 'val') { + this.boy.emit('field', decodeText(this._key, 'binary', this.charset), + decodeText(this._val, 'binary', this.charset), + this._keyTrunc, + this._valTrunc) + } + this.boy._done = true + this.boy.emit('finish') +} + +module.exports = UrlEncoded + + +/***/ }), + +/***/ 349: +/***/ ((module) => { + +"use strict"; + + +const RE_PLUS = /\+/g + +const HEX = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +] + +function Decoder () { + this.buffer = undefined +} +Decoder.prototype.write = function (str) { + // Replace '+' with ' ' before decoding + str = str.replace(RE_PLUS, ' ') + let res = '' + let i = 0; let p = 0; const len = str.length + for (; i < len; ++i) { + if (this.buffer !== undefined) { + if (!HEX[str.charCodeAt(i)]) { + res += '%' + this.buffer + this.buffer = undefined + --i // retry character + } else { + this.buffer += str[i] + ++p + if (this.buffer.length === 2) { + res += String.fromCharCode(parseInt(this.buffer, 16)) + this.buffer = undefined + } + } + } else if (str[i] === '%') { + if (i > p) { + res += str.substring(p, i) + p = i + } + this.buffer = '' + ++p + } + } + if (p < len && this.buffer === undefined) { res += str.substring(p) } + return res +} +Decoder.prototype.reset = function () { + this.buffer = undefined +} + +module.exports = Decoder + + +/***/ }), + +/***/ 299: +/***/ ((module) => { + +"use strict"; + + +module.exports = function basename (path) { + if (typeof path !== 'string') { return '' } + for (var i = path.length - 1; i >= 0; --i) { // eslint-disable-line no-var + switch (path.charCodeAt(i)) { + case 0x2F: // '/' + case 0x5C: // '\' + path = path.slice(i + 1) + return (path === '..' || path === '.' ? '' : path) + } + } + return (path === '..' || path === '.' ? '' : path) +} + + +/***/ }), + +/***/ 2491: +/***/ (function(module) { + +"use strict"; + + +// Node has always utf-8 +const utf8Decoder = new TextDecoder('utf-8') +const textDecoders = new Map([ + ['utf-8', utf8Decoder], + ['utf8', utf8Decoder] +]) + +function getDecoder (charset) { + let lc + while (true) { + switch (charset) { + case 'utf-8': + case 'utf8': + return decoders.utf8 + case 'latin1': + case 'ascii': // TODO: Make these a separate, strict decoder? + case 'us-ascii': + case 'iso-8859-1': + case 'iso8859-1': + case 'iso88591': + case 'iso_8859-1': + case 'windows-1252': + case 'iso_8859-1:1987': + case 'cp1252': + case 'x-cp1252': + return decoders.latin1 + case 'utf16le': + case 'utf-16le': + case 'ucs2': + case 'ucs-2': + return decoders.utf16le + case 'base64': + return decoders.base64 + default: + if (lc === undefined) { + lc = true + charset = charset.toLowerCase() + continue + } + return decoders.other.bind(charset) + } + } +} + +const decoders = { + utf8: (data, sourceEncoding) => { + if (data.length === 0) { + return '' + } + if (typeof data === 'string') { + data = Buffer.from(data, sourceEncoding) + } + return data.utf8Slice(0, data.length) + }, + + latin1: (data, sourceEncoding) => { + if (data.length === 0) { + return '' + } + if (typeof data === 'string') { + return data + } + return data.latin1Slice(0, data.length) + }, + + utf16le: (data, sourceEncoding) => { + if (data.length === 0) { + return '' + } + if (typeof data === 'string') { + data = Buffer.from(data, sourceEncoding) + } + return data.ucs2Slice(0, data.length) + }, + + base64: (data, sourceEncoding) => { + if (data.length === 0) { + return '' + } + if (typeof data === 'string') { + data = Buffer.from(data, sourceEncoding) + } + return data.base64Slice(0, data.length) + }, + + other: (data, sourceEncoding) => { + if (data.length === 0) { + return '' + } + if (typeof data === 'string') { + data = Buffer.from(data, sourceEncoding) + } + + if (textDecoders.has(this.toString())) { + try { + return textDecoders.get(this).decode(data) + } catch (e) { } + } + return typeof data === 'string' + ? data + : data.toString() + } +} + +function decodeText (text, sourceEncoding, destEncoding) { + if (text) { + return getDecoder(destEncoding)(text, sourceEncoding) + } + return text +} + +module.exports = decodeText + + +/***/ }), + +/***/ 8459: +/***/ ((module) => { + +"use strict"; + + +module.exports = function getLimit (limits, name, defaultLimit) { + if ( + !limits || + limits[name] === undefined || + limits[name] === null + ) { return defaultLimit } + + if ( + typeof limits[name] !== 'number' || + isNaN(limits[name]) + ) { throw new TypeError('Limit ' + name + ' is not a valid number') } + + return limits[name] +} + + +/***/ }), + +/***/ 1133: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; +/* eslint-disable object-property-newline */ + + +const decodeText = __nccwpck_require__(2491) + +const RE_ENCODED = /%[a-fA-F0-9][a-fA-F0-9]/g + +const EncodedLookup = { + '%00': '\x00', '%01': '\x01', '%02': '\x02', '%03': '\x03', '%04': '\x04', + '%05': '\x05', '%06': '\x06', '%07': '\x07', '%08': '\x08', '%09': '\x09', + '%0a': '\x0a', '%0A': '\x0a', '%0b': '\x0b', '%0B': '\x0b', '%0c': '\x0c', + '%0C': '\x0c', '%0d': '\x0d', '%0D': '\x0d', '%0e': '\x0e', '%0E': '\x0e', + '%0f': '\x0f', '%0F': '\x0f', '%10': '\x10', '%11': '\x11', '%12': '\x12', + '%13': '\x13', '%14': '\x14', '%15': '\x15', '%16': '\x16', '%17': '\x17', + '%18': '\x18', '%19': '\x19', '%1a': '\x1a', '%1A': '\x1a', '%1b': '\x1b', + '%1B': '\x1b', '%1c': '\x1c', '%1C': '\x1c', '%1d': '\x1d', '%1D': '\x1d', + '%1e': '\x1e', '%1E': '\x1e', '%1f': '\x1f', '%1F': '\x1f', '%20': '\x20', + '%21': '\x21', '%22': '\x22', '%23': '\x23', '%24': '\x24', '%25': '\x25', + '%26': '\x26', '%27': '\x27', '%28': '\x28', '%29': '\x29', '%2a': '\x2a', + '%2A': '\x2a', '%2b': '\x2b', '%2B': '\x2b', '%2c': '\x2c', '%2C': '\x2c', + '%2d': '\x2d', '%2D': '\x2d', '%2e': '\x2e', '%2E': '\x2e', '%2f': '\x2f', + '%2F': '\x2f', '%30': '\x30', '%31': '\x31', '%32': '\x32', '%33': '\x33', + '%34': '\x34', '%35': '\x35', '%36': '\x36', '%37': '\x37', '%38': '\x38', + '%39': '\x39', '%3a': '\x3a', '%3A': '\x3a', '%3b': '\x3b', '%3B': '\x3b', + '%3c': '\x3c', '%3C': '\x3c', '%3d': '\x3d', '%3D': '\x3d', '%3e': '\x3e', + '%3E': '\x3e', '%3f': '\x3f', '%3F': '\x3f', '%40': '\x40', '%41': '\x41', + '%42': '\x42', '%43': '\x43', '%44': '\x44', '%45': '\x45', '%46': '\x46', + '%47': '\x47', '%48': '\x48', '%49': '\x49', '%4a': '\x4a', '%4A': '\x4a', + '%4b': '\x4b', '%4B': '\x4b', '%4c': '\x4c', '%4C': '\x4c', '%4d': '\x4d', + '%4D': '\x4d', '%4e': '\x4e', '%4E': '\x4e', '%4f': '\x4f', '%4F': '\x4f', + '%50': '\x50', '%51': '\x51', '%52': '\x52', '%53': '\x53', '%54': '\x54', + '%55': '\x55', '%56': '\x56', '%57': '\x57', '%58': '\x58', '%59': '\x59', + '%5a': '\x5a', '%5A': '\x5a', '%5b': '\x5b', '%5B': '\x5b', '%5c': '\x5c', + '%5C': '\x5c', '%5d': '\x5d', '%5D': '\x5d', '%5e': '\x5e', '%5E': '\x5e', + '%5f': '\x5f', '%5F': '\x5f', '%60': '\x60', '%61': '\x61', '%62': '\x62', + '%63': '\x63', '%64': '\x64', '%65': '\x65', '%66': '\x66', '%67': '\x67', + '%68': '\x68', '%69': '\x69', '%6a': '\x6a', '%6A': '\x6a', '%6b': '\x6b', + '%6B': '\x6b', '%6c': '\x6c', '%6C': '\x6c', '%6d': '\x6d', '%6D': '\x6d', + '%6e': '\x6e', '%6E': '\x6e', '%6f': '\x6f', '%6F': '\x6f', '%70': '\x70', + '%71': '\x71', '%72': '\x72', '%73': '\x73', '%74': '\x74', '%75': '\x75', + '%76': '\x76', '%77': '\x77', '%78': '\x78', '%79': '\x79', '%7a': '\x7a', + '%7A': '\x7a', '%7b': '\x7b', '%7B': '\x7b', '%7c': '\x7c', '%7C': '\x7c', + '%7d': '\x7d', '%7D': '\x7d', '%7e': '\x7e', '%7E': '\x7e', '%7f': '\x7f', + '%7F': '\x7f', '%80': '\x80', '%81': '\x81', '%82': '\x82', '%83': '\x83', + '%84': '\x84', '%85': '\x85', '%86': '\x86', '%87': '\x87', '%88': '\x88', + '%89': '\x89', '%8a': '\x8a', '%8A': '\x8a', '%8b': '\x8b', '%8B': '\x8b', + '%8c': '\x8c', '%8C': '\x8c', '%8d': '\x8d', '%8D': '\x8d', '%8e': '\x8e', + '%8E': '\x8e', '%8f': '\x8f', '%8F': '\x8f', '%90': '\x90', '%91': '\x91', + '%92': '\x92', '%93': '\x93', '%94': '\x94', '%95': '\x95', '%96': '\x96', + '%97': '\x97', '%98': '\x98', '%99': '\x99', '%9a': '\x9a', '%9A': '\x9a', + '%9b': '\x9b', '%9B': '\x9b', '%9c': '\x9c', '%9C': '\x9c', '%9d': '\x9d', + '%9D': '\x9d', '%9e': '\x9e', '%9E': '\x9e', '%9f': '\x9f', '%9F': '\x9f', + '%a0': '\xa0', '%A0': '\xa0', '%a1': '\xa1', '%A1': '\xa1', '%a2': '\xa2', + '%A2': '\xa2', '%a3': '\xa3', '%A3': '\xa3', '%a4': '\xa4', '%A4': '\xa4', + '%a5': '\xa5', '%A5': '\xa5', '%a6': '\xa6', '%A6': '\xa6', '%a7': '\xa7', + '%A7': '\xa7', '%a8': '\xa8', '%A8': '\xa8', '%a9': '\xa9', '%A9': '\xa9', + '%aa': '\xaa', '%Aa': '\xaa', '%aA': '\xaa', '%AA': '\xaa', '%ab': '\xab', + '%Ab': '\xab', '%aB': '\xab', '%AB': '\xab', '%ac': '\xac', '%Ac': '\xac', + '%aC': '\xac', '%AC': '\xac', '%ad': '\xad', '%Ad': '\xad', '%aD': '\xad', + '%AD': '\xad', '%ae': '\xae', '%Ae': '\xae', '%aE': '\xae', '%AE': '\xae', + '%af': '\xaf', '%Af': '\xaf', '%aF': '\xaf', '%AF': '\xaf', '%b0': '\xb0', + '%B0': '\xb0', '%b1': '\xb1', '%B1': '\xb1', '%b2': '\xb2', '%B2': '\xb2', + '%b3': '\xb3', '%B3': '\xb3', '%b4': '\xb4', '%B4': '\xb4', '%b5': '\xb5', + '%B5': '\xb5', '%b6': '\xb6', '%B6': '\xb6', '%b7': '\xb7', '%B7': '\xb7', + '%b8': '\xb8', '%B8': '\xb8', '%b9': '\xb9', '%B9': '\xb9', '%ba': '\xba', + '%Ba': '\xba', '%bA': '\xba', '%BA': '\xba', '%bb': '\xbb', '%Bb': '\xbb', + '%bB': '\xbb', '%BB': '\xbb', '%bc': '\xbc', '%Bc': '\xbc', '%bC': '\xbc', + '%BC': '\xbc', '%bd': '\xbd', '%Bd': '\xbd', '%bD': '\xbd', '%BD': '\xbd', + '%be': '\xbe', '%Be': '\xbe', '%bE': '\xbe', '%BE': '\xbe', '%bf': '\xbf', + '%Bf': '\xbf', '%bF': '\xbf', '%BF': '\xbf', '%c0': '\xc0', '%C0': '\xc0', + '%c1': '\xc1', '%C1': '\xc1', '%c2': '\xc2', '%C2': '\xc2', '%c3': '\xc3', + '%C3': '\xc3', '%c4': '\xc4', '%C4': '\xc4', '%c5': '\xc5', '%C5': '\xc5', + '%c6': '\xc6', '%C6': '\xc6', '%c7': '\xc7', '%C7': '\xc7', '%c8': '\xc8', + '%C8': '\xc8', '%c9': '\xc9', '%C9': '\xc9', '%ca': '\xca', '%Ca': '\xca', + '%cA': '\xca', '%CA': '\xca', '%cb': '\xcb', '%Cb': '\xcb', '%cB': '\xcb', + '%CB': '\xcb', '%cc': '\xcc', '%Cc': '\xcc', '%cC': '\xcc', '%CC': '\xcc', + '%cd': '\xcd', '%Cd': '\xcd', '%cD': '\xcd', '%CD': '\xcd', '%ce': '\xce', + '%Ce': '\xce', '%cE': '\xce', '%CE': '\xce', '%cf': '\xcf', '%Cf': '\xcf', + '%cF': '\xcf', '%CF': '\xcf', '%d0': '\xd0', '%D0': '\xd0', '%d1': '\xd1', + '%D1': '\xd1', '%d2': '\xd2', '%D2': '\xd2', '%d3': '\xd3', '%D3': '\xd3', + '%d4': '\xd4', '%D4': '\xd4', '%d5': '\xd5', '%D5': '\xd5', '%d6': '\xd6', + '%D6': '\xd6', '%d7': '\xd7', '%D7': '\xd7', '%d8': '\xd8', '%D8': '\xd8', + '%d9': '\xd9', '%D9': '\xd9', '%da': '\xda', '%Da': '\xda', '%dA': '\xda', + '%DA': '\xda', '%db': '\xdb', '%Db': '\xdb', '%dB': '\xdb', '%DB': '\xdb', + '%dc': '\xdc', '%Dc': '\xdc', '%dC': '\xdc', '%DC': '\xdc', '%dd': '\xdd', + '%Dd': '\xdd', '%dD': '\xdd', '%DD': '\xdd', '%de': '\xde', '%De': '\xde', + '%dE': '\xde', '%DE': '\xde', '%df': '\xdf', '%Df': '\xdf', '%dF': '\xdf', + '%DF': '\xdf', '%e0': '\xe0', '%E0': '\xe0', '%e1': '\xe1', '%E1': '\xe1', + '%e2': '\xe2', '%E2': '\xe2', '%e3': '\xe3', '%E3': '\xe3', '%e4': '\xe4', + '%E4': '\xe4', '%e5': '\xe5', '%E5': '\xe5', '%e6': '\xe6', '%E6': '\xe6', + '%e7': '\xe7', '%E7': '\xe7', '%e8': '\xe8', '%E8': '\xe8', '%e9': '\xe9', + '%E9': '\xe9', '%ea': '\xea', '%Ea': '\xea', '%eA': '\xea', '%EA': '\xea', + '%eb': '\xeb', '%Eb': '\xeb', '%eB': '\xeb', '%EB': '\xeb', '%ec': '\xec', + '%Ec': '\xec', '%eC': '\xec', '%EC': '\xec', '%ed': '\xed', '%Ed': '\xed', + '%eD': '\xed', '%ED': '\xed', '%ee': '\xee', '%Ee': '\xee', '%eE': '\xee', + '%EE': '\xee', '%ef': '\xef', '%Ef': '\xef', '%eF': '\xef', '%EF': '\xef', + '%f0': '\xf0', '%F0': '\xf0', '%f1': '\xf1', '%F1': '\xf1', '%f2': '\xf2', + '%F2': '\xf2', '%f3': '\xf3', '%F3': '\xf3', '%f4': '\xf4', '%F4': '\xf4', + '%f5': '\xf5', '%F5': '\xf5', '%f6': '\xf6', '%F6': '\xf6', '%f7': '\xf7', + '%F7': '\xf7', '%f8': '\xf8', '%F8': '\xf8', '%f9': '\xf9', '%F9': '\xf9', + '%fa': '\xfa', '%Fa': '\xfa', '%fA': '\xfa', '%FA': '\xfa', '%fb': '\xfb', + '%Fb': '\xfb', '%fB': '\xfb', '%FB': '\xfb', '%fc': '\xfc', '%Fc': '\xfc', + '%fC': '\xfc', '%FC': '\xfc', '%fd': '\xfd', '%Fd': '\xfd', '%fD': '\xfd', + '%FD': '\xfd', '%fe': '\xfe', '%Fe': '\xfe', '%fE': '\xfe', '%FE': '\xfe', + '%ff': '\xff', '%Ff': '\xff', '%fF': '\xff', '%FF': '\xff' +} + +function encodedReplacer (match) { + return EncodedLookup[match] +} + +const STATE_KEY = 0 +const STATE_VALUE = 1 +const STATE_CHARSET = 2 +const STATE_LANG = 3 + +function parseParams (str) { + const res = [] + let state = STATE_KEY + let charset = '' + let inquote = false + let escaping = false + let p = 0 + let tmp = '' + const len = str.length + + for (var i = 0; i < len; ++i) { // eslint-disable-line no-var + const char = str[i] + if (char === '\\' && inquote) { + if (escaping) { escaping = false } else { + escaping = true + continue + } + } else if (char === '"') { + if (!escaping) { + if (inquote) { + inquote = false + state = STATE_KEY + } else { inquote = true } + continue + } else { escaping = false } + } else { + if (escaping && inquote) { tmp += '\\' } + escaping = false + if ((state === STATE_CHARSET || state === STATE_LANG) && char === "'") { + if (state === STATE_CHARSET) { + state = STATE_LANG + charset = tmp.substring(1) + } else { state = STATE_VALUE } + tmp = '' + continue + } else if (state === STATE_KEY && + (char === '*' || char === '=') && + res.length) { + state = char === '*' + ? STATE_CHARSET + : STATE_VALUE + res[p] = [tmp, undefined] + tmp = '' + continue + } else if (!inquote && char === ';') { + state = STATE_KEY + if (charset) { + if (tmp.length) { + tmp = decodeText(tmp.replace(RE_ENCODED, encodedReplacer), + 'binary', + charset) + } + charset = '' + } else if (tmp.length) { + tmp = decodeText(tmp, 'binary', 'utf8') + } + if (res[p] === undefined) { res[p] = tmp } else { res[p][1] = tmp } + tmp = '' + ++p + continue + } else if (!inquote && (char === ' ' || char === '\t')) { continue } + } + tmp += char + } + if (charset && tmp.length) { + tmp = decodeText(tmp.replace(RE_ENCODED, encodedReplacer), + 'binary', + charset) + } else if (tmp) { + tmp = decodeText(tmp, 'binary', 'utf8') + } + + if (res[p] === undefined) { + if (tmp) { res[p] = tmp } + } else { res[p][1] = tmp } + + return res +} + +module.exports = parseParams + + +/***/ }) + +/******/ }); +/************************************************************************/ +/******/ // The module cache +/******/ var __webpack_module_cache__ = {}; +/******/ +/******/ // The require function +/******/ function __nccwpck_require__(moduleId) { +/******/ // Check if module is in cache +/******/ var cachedModule = __webpack_module_cache__[moduleId]; +/******/ if (cachedModule !== undefined) { +/******/ return cachedModule.exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = __webpack_module_cache__[moduleId] = { +/******/ // no module.id needed +/******/ // no module.loaded needed +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ var threw = true; +/******/ try { +/******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __nccwpck_require__); +/******/ threw = false; +/******/ } finally { +/******/ if(threw) delete __webpack_module_cache__[moduleId]; +/******/ } +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/compat */ +/******/ +/******/ if (typeof __nccwpck_require__ !== 'undefined') __nccwpck_require__.ab = __dirname + "/"; +/******/ +/************************************************************************/ +/******/ +/******/ // startup +/******/ // Load entry module and return exports +/******/ // This entry module is referenced by other modules so it can't be inlined +/******/ var __webpack_exports__ = __nccwpck_require__(9254); +/******/ module.exports = __webpack_exports__; +/******/ +/******/ })() +; \ No newline at end of file diff --git a/.github/actions/node/package.json b/.github/actions/node/package.json new file mode 100644 index 0000000000..b202321a35 --- /dev/null +++ b/.github/actions/node/package.json @@ -0,0 +1,26 @@ +{ + "name": "docker", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "tsc && ncc build --no-cache src/index.ts -o dist && cp dist/index.js builder/index.js" + }, + "dependencies": { + "@actions/core": "^1.10.1", + "@actions/exec": "^1.1.1", + "@actions/io": "^1.1.3", + "dotenv": "8.2.0" + }, + "devDependencies": { + "@types/node": "^20.10.6", + "@typescript-eslint/eslint-plugin": "^6.7.4", + "@typescript-eslint/parser": "^6.7.4", + "@vercel/ncc": "^0.38.1", + "eslint": "^8.50.0", + "eslint-config-prettier": "^9.0.0", + "eslint-plugin-prettier": "^5.0.0", + "prettier": "^3.0.3", + "ts-node": "^10.9.1", + "typescript": "^5.2.2" + } +} diff --git a/.github/actions/node/src/index.ts b/.github/actions/node/src/index.ts new file mode 100644 index 0000000000..c7b84b5ccd --- /dev/null +++ b/.github/actions/node/src/index.ts @@ -0,0 +1,48 @@ +import { buildStep, deployStep, pushStep } from './steps' +import { getInputs } from './inputs' +import { IS_POST } from './state' +import * as core from '@actions/core' +import { ActionStep } from './types' +/** + * Runs the action + */ +async function run() { + const inputs = await getInputs() + + for (const step of inputs.steps) { + core.info(`Running step: ${step}`) + switch (step) { + case ActionStep.BUILD: { + await buildStep() + break + } + + case ActionStep.PUSH: { + await pushStep() + break + } + + case ActionStep.DEPLOY: { + await deployStep() + break + } + + default: + core.error(`Unknown action step: ${step}!`) + throw new Error(`Unknown action step: ${step}!`) + } + } +} + +/** + * Runs the post action cleanup step + */ +async function post() {} + +setImmediate(async () => { + if (!IS_POST) { + await run() + } else { + await post() + } +}) diff --git a/.github/actions/node/src/inputs.ts b/.github/actions/node/src/inputs.ts new file mode 100644 index 0000000000..44383bb2f4 --- /dev/null +++ b/.github/actions/node/src/inputs.ts @@ -0,0 +1,167 @@ +import { + ActionStep, + CloudEnvironment, + IActionInputs, + IBuildInput, + IDeployInput, + IPushInput, +} from './types' +import * as core from '@actions/core' +import { getBuilderDefinitions } from './utils' + +const getBuildInputs = (): IBuildInput => { + const tag = core.getInput('tag') + + return { + tag, + images: [], + } +} + +const getPushInputs = (): IPushInput => { + const username = process.env.DOCKERHUB_USERNAME + if (!username) { + core.error('No DockerHub username found in DOCKERHUB_USERNAME environment variable!') + throw new Error('No DockerHub username found in DOCKERHUB_USERNAME environment variable!') + } + + const password = process.env.DOCKERHUB_PASSWORD + if (!password) { + core.error('No DockerHub password found in DOCKERHUB_PASSWORD environment variable!') + throw new Error('No DockerHub password found in DOCKERHUB_PASSWORD environment variable!') + } + + return { + dockerUsername: username, + dockerPassword: password, + } +} + +const getDeployIUputs = (): IDeployInput => { + const services = getInputList('services') + + const cloudEnvironment = process.env['CLOUD_ENV'] as CloudEnvironment + if (!cloudEnvironment) { + core.error('No CLOUD_ENV environment variable found!') + throw new Error('No CLOUD_ENV environment variable found!') + } + + const eksClusterName = process.env.CROWD_CLUSTER + if (!eksClusterName) { + core.error('No CROWD_CLUSTER environment variable found!') + throw new Error('No CROWD_CLUSTER environment variable found!') + } + + const awsRoleArn = process.env.CROWD_ROLE_ARN + if (!awsRoleArn) { + core.error('No CROWD_ROLE_ARN environment variable found!') + throw new Error('No CROWD_ROLE_ARN environment variable found!') + } + + const awsAccessKeyId = process.env.AWS_ACCESS_KEY_ID + if (!awsAccessKeyId) { + core.error('No AWS_ACCESS_KEY_ID environment variable found!') + throw new Error('No AWS_ACCESS_KEY_ID environment variable found!') + } + + const awsSecretAccessKey = process.env.AWS_SECRET_ACCESS_KEY + if (!awsSecretAccessKey) { + core.error('No AWS_SECRET_ACCESS_KEY environment variable found!') + throw new Error('No AWS_SECRET_ACCESS_KEY environment variable found!') + } + + const awsRegion = process.env.AWS_REGION + if (!awsRegion) { + core.error('No AWS_REGION environment variable found!') + throw new Error('No AWS_REGION environment variable found!') + } + + return { + services, + cloudEnvironment, + eksClusterName, + awsRoleArn, + awsAccessKeyId, + awsSecretAccessKey, + awsRegion, + } +} + +let inputs: IActionInputs | undefined +export const getInputs = async (): Promise => { + if (inputs !== undefined) { + return inputs + } + + const actionSteps = getInputList('steps') as ActionStep[] + + if (actionSteps.length === 0) { + core.error('No action steps provided!') + throw new Error('No action steps provided!') + } + + const results: IActionInputs = { + steps: actionSteps, + } + + for (const step of actionSteps) { + switch (step) { + case ActionStep.BUILD: + results[ActionStep.BUILD] = getBuildInputs() + break + case ActionStep.PUSH: + results[ActionStep.PUSH] = getPushInputs() + break + case ActionStep.DEPLOY: + results[ActionStep.DEPLOY] = getDeployIUputs() + break + + default: + core.error(`Unknown action step: ${step}!`) + throw new Error(`Unknown action step: ${step}!`) + } + } + + if (results[ActionStep.BUILD] !== undefined) { + if (results[ActionStep.BUILD].images.length === 0 && results[ActionStep.DEPLOY] !== undefined) { + // calculate images from services + const buildDefinitions = await getBuilderDefinitions() + + const images: string[] = [] + for (const service of results[ActionStep.DEPLOY].services) { + const definition = buildDefinitions.find((d) => d.services.includes(service)) + if (definition === undefined) { + core.error(`No builder definition found for service: ${service}!`) + throw new Error(`No builder definition found for service: ${service}!`) + } + + if (!images.includes(definition.imageName)) { + images.push(definition.imageName) + } + } + + results[ActionStep.BUILD].images = images + } + } + + if (results[ActionStep.PUSH] !== undefined && results[ActionStep.BUILD] === undefined) { + core.error('Push step provided without build step!') + throw new Error('Push step provided without build step!') + } + + if (results[ActionStep.DEPLOY] !== undefined && results[ActionStep.PUSH] === undefined) { + core.error('Deploy step provided without push step!') + throw new Error('Deploy step provided without push step!') + } + + inputs = results + return results +} + +const getInputList = (name: string): string[] => { + const items = core.getInput(name) + return items + .split(' ') + .map((s) => s.trim()) + .filter((s) => s.length > 0) +} diff --git a/.github/actions/node/src/state.ts b/.github/actions/node/src/state.ts new file mode 100644 index 0000000000..e6e888085c --- /dev/null +++ b/.github/actions/node/src/state.ts @@ -0,0 +1,7 @@ +import * as core from '@actions/core' + +export const IS_POST = !!process.env['STATE_isPost'] + +if (!IS_POST) { + core.saveState('isPost', 'true') +} diff --git a/.github/actions/node/src/steps.ts b/.github/actions/node/src/steps.ts new file mode 100644 index 0000000000..32395be9ea --- /dev/null +++ b/.github/actions/node/src/steps.ts @@ -0,0 +1,244 @@ +import { getInputs } from './inputs' +import { ActionStep, CloudEnvironment, IBuilderDefinition } from './types' +import * as core from '@actions/core' +import * as exec from '@actions/exec' +import { getBuilderDefinitions } from './utils' + +const imageTagMap = new Map() + +export const buildStep = async (): Promise => { + const inputs = await getInputs() + + if (inputs[ActionStep.BUILD] === undefined) { + core.error('No build inputs provided!') + throw new Error('No build inputs provided!') + } + + const { images, tag } = inputs[ActionStep.BUILD] + if (images.length === 0) { + core.error('No images provided!') + throw new Error('No images provided!') + } + + if (!tag) { + core.error('No tag provided!') + throw new Error('No tag provided!') + } + + const timestamp = Math.floor(Date.now() / 1000) + + const actualTag = `${tag}.${timestamp}` + + const alreadyBuilt: string[] = [] + + for (const image of images) { + if (alreadyBuilt.includes(image)) { + core.info(`Skipping already built image: ${image}:${actualTag}`) + continue + } + + core.info(`Building image: ${image}:${actualTag}`) + const exitCode = await exec.exec('bash', ['cli', 'build', image, actualTag], { + cwd: './scripts', + }) + + if (exitCode !== 0) { + core.error(`Failed to build image: ${image}:${actualTag}`) + } else { + alreadyBuilt.push(image) + imageTagMap.set(image, actualTag) + } + } +} + +export const pushStep = async (): Promise => { + const inputs = await getInputs() + const images = inputs[ActionStep.BUILD]?.images ?? [] + const pushInput = inputs[ActionStep.PUSH] + if (!pushInput) { + core.error('No push inputs provided!') + throw new Error('No push inputs provided!') + } + + if (images.length === 0) { + core.error('No images provided!') + throw new Error('No images provided!') + } + + // do a docker login + const exitCode = await exec.exec('docker', [ + 'login', + '--username', + pushInput.dockerUsername, + '--password', + pushInput.dockerPassword, + ]) + + if (exitCode !== 0) { + core.error('Failed to login to docker!') + throw new Error('Failed to login to docker!') + } + + // now push the images + const alreadyPushed: string[] = [] + for (const image of images) { + if (alreadyPushed.includes(image)) { + core.info(`Skipping already pushed image: ${image}`) + continue + } + + if (!imageTagMap.has(image)) { + core.warning(`No tag found for image: ${image} - image wasn't built successfully!`) + continue + } + + const tag = imageTagMap.get(image) + + core.info(`Pushing image: ${image}:${tag}!`) + + const exitCode = await exec.exec('bash', ['cli', 'push', image, tag], { + cwd: './scripts', + }) + + if (exitCode !== 0) { + core.error(`Failed to push image: ${image}:${tag}`) + imageTagMap.delete(image) + } else { + alreadyPushed.push(image) + } + } +} + +export const deployStep = async (): Promise => { + const inputs = await getInputs() + + const deployInput = inputs[ActionStep.DEPLOY] + if (!deployInput) { + core.error('No deploy inputs provided!') + throw new Error('No deploy inputs provided!') + } + + if (deployInput.services.length === 0) { + core.warning('No services specified for deploy!') + return + } + + // check if any images failed to build + const builderDefinitions = await getBuilderDefinitions() + + const servicesToDeploy: { service: string; tag: string; builderDef: IBuilderDefinition }[] = [] + for (const service of deployInput.services) { + const builderDef = builderDefinitions.find((b) => b.services.includes(service)) + + if (!builderDef) { + core.error(`No builder definition found for service: ${service}`) + throw new Error(`No builder definition found for service: ${service}`) + } + + if (!imageTagMap.has(builderDef.imageName)) { + core.error( + `No tag found for image: ${builderDef.imageName} - image wasn't built successfully!`, + ) + throw new Error( + `No tag found for image: ${builderDef.imageName} - image wasn't built successfully!`, + ) + } + + const tag = imageTagMap.get(builderDef.imageName) + + servicesToDeploy.push({ + service, + tag, + builderDef, + }) + } + + const env = { + AWS_ACCESS_KEY_ID: deployInput.awsAccessKeyId, + AWS_SECRET_ACCESS_KEY: deployInput.awsSecretAccessKey, + AWS_REGION: deployInput.awsRegion, + } + + let exitCode = await exec.exec( + 'aws', + [ + 'eks', + 'update-kubeconfig', + '--name', + deployInput.eksClusterName, + '--role-arn', + deployInput.awsRoleArn, + ], + { + env, + }, + ) + + if (exitCode !== 0) { + core.error('Failed to update kubeconfig!') + throw new Error('Failed to update kubeconfig!') + } + + let failed = [] + + for (const serviceDef of servicesToDeploy) { + const tag = serviceDef.tag + const service = serviceDef.service + const prioritized = serviceDef.builderDef.prioritizedServices.includes(service) + const servicesToUpdate: string[] = [] + + if (prioritized) { + switch (deployInput.cloudEnvironment) { + case CloudEnvironment.PRODUCTION: { + servicesToUpdate.push( + ...[`${service}-system`, `${service}-normal`, `${service}-high`, `${service}-urgent`], + ) + break + } + case CloudEnvironment.LF_PRODUCTION: { + servicesToUpdate.push(...[`${service}-system`, `${service}-normal`, `${service}-high`]) + break + } + + case CloudEnvironment.LF_STAGING: + case CloudEnvironment.STAGING: { + servicesToUpdate.push(`${service}-normal`) + break + } + + default: + core.error(`Unknown cloud environment: ${deployInput.cloudEnvironment}`) + throw new Error(`Unknown cloud environment: ${deployInput.cloudEnvironment}`) + } + } else { + servicesToUpdate.push(service) + } + + core.info( + `Deploying service: ${service} with image: ${ + serviceDef.builderDef.dockerRepository + }:${tag} to deployments: ${servicesToUpdate.join(', ')}`, + ) + + for (const toDeploy of servicesToUpdate) { + exitCode = await exec.exec('kubectl', [ + 'set', + 'image', + `deployments/${toDeploy}-dpl`, + `${toDeploy}=${serviceDef.builderDef.dockerRepository}:${tag}`, + ]) + + if (exitCode !== 0) { + core.error(`Failed to deploy service: ${service} to deployment: ${toDeploy}`) + if (!failed.includes(service)) { + failed.push(service) + } + } + } + } + + if (failed.length > 0) { + core.error(`Failed to deploy services: ${failed.join(', ')}`) + throw new Error(`Failed to deploy services: ${failed.join(', ')}`) + } +} diff --git a/.github/actions/node/src/types.ts b/.github/actions/node/src/types.ts new file mode 100644 index 0000000000..b4ce3c3879 --- /dev/null +++ b/.github/actions/node/src/types.ts @@ -0,0 +1,55 @@ +export enum ActionStep { + BUILD = 'build', + PUSH = 'push', + DEPLOY = 'deploy', +} + +export enum CloudEnvironment { + PRODUCTION = 'production', + STAGING = 'staging', + LF_PRODUCTION = 'lf-production', + LF_STAGING = 'lf-staging', +} + +export interface IBuildInput { + // image version tag + tag: string + + // images to build + images: string[] +} + +export interface IPushInput { + // docker credentials to push image to + dockerUsername: string + dockerPassword: string +} + +export interface IDeployInput { + // services to deploy + services: string[] + + // which cloud environment are we deploying to + cloudEnvironment: CloudEnvironment + + // aws credentials to use when deploying + eksClusterName: string + awsRoleArn: string + awsAccessKeyId: string + awsSecretAccessKey: string + awsRegion: string +} + +export interface IBuilderDefinition { + imageName: string + dockerRepository: string + services: string[] + prioritizedServices: string[] +} + +export type IActionInputs = { + steps: ActionStep[] + [ActionStep.BUILD]?: IBuildInput + [ActionStep.PUSH]?: IPushInput + [ActionStep.DEPLOY]?: IDeployInput +} diff --git a/.github/actions/node/src/utils.ts b/.github/actions/node/src/utils.ts new file mode 100644 index 0000000000..c2cd6671bd --- /dev/null +++ b/.github/actions/node/src/utils.ts @@ -0,0 +1,48 @@ +import dotenv from 'dotenv' +import { IBuilderDefinition } from './types' +import fs from 'fs' + +let definitions: IBuilderDefinition[] | undefined + +export const getBuilderDefinitions = async (): Promise => { + if (definitions !== undefined) { + return definitions + } + + const results: IBuilderDefinition[] = [] + const files = fs.readdirSync('./scripts/builders') + + for (const result of files) { + if (result.endsWith('.env')) { + const content = fs.readFileSync(`./scripts/builders/${result}`, 'utf-8') + const parsed = dotenv.parse(content) + + const imageName = result.split('.env')[0] + const dockerRepository = parsed.REPO + let services: string[] = [] + if (parsed.SERVICES !== undefined) { + services = parsed.SERVICES.split(' ') + .map((s) => s.trim()) + .filter((s) => s.length > 0) + } + + let prioritizedServices: string[] = [] + if (parsed.PRIORITIZED !== undefined) { + prioritizedServices = parsed.PRIORITIZED.split(' ') + .map((s) => s.trim()) + .filter((s) => s.length > 0) + } + + results.push({ + imageName, + dockerRepository, + services, + prioritizedServices, + }) + } + } + + definitions = results + + return results +} diff --git a/.github/actions/node/tsconfig.json b/.github/actions/node/tsconfig.json new file mode 100644 index 0000000000..4cf9afb8fc --- /dev/null +++ b/.github/actions/node/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "target": "es2017", + "module": "Node16", + "lib": ["es6", "es7", "es2017", "es2017.object", "es2015.promise", "ES2021.String"], + "skipLibCheck": true, + "sourceMap": true, + "moduleResolution": "node16", + "experimentalDecorators": true, + "esModuleInterop": true, + "baseUrl": "./src", + "outDir": "./out", + "paths": { + "@/*": ["*"] + } + }, + "include": ["src/**/*"] +} diff --git a/.github/workflows/lf-production-deploy-new.yaml b/.github/workflows/lf-production-deploy-new.yaml deleted file mode 100644 index 4ce5052b2c..0000000000 --- a/.github/workflows/lf-production-deploy-new.yaml +++ /dev/null @@ -1,318 +0,0 @@ -name: LF Production Deploy New - -on: - workflow_dispatch: - inputs: - deploy_search_sync_worker: - description: Deploy search-sync-worker service? - required: true - type: boolean - deploy_search_sync_api: - description: Deploy search-sync-api service? - required: true - type: boolean - deploy_integration_sync_worker: - description: Deploy integration-sync-worker service? - required: true - type: boolean - deploy_webhook_api: - description: Deploy webhook-api service? - required: true - type: boolean - deploy_automations_worker: - description: Deploy automations-worker service? - required: true - type: boolean - deploy_emails_worker: - description: Deploy emails-worker service? - required: true - type: boolean - deploy_script_executor: - description: Deploy script-executor service? - required: true - type: boolean - -env: - DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} - DOCKERHUB_PASSWORD: ${{ secrets.DOCKERHUB_PASSWORD }} - CROWD_CLUSTER: ${{ secrets.LF_PRODUCTION_CLUSTER_NAME }} - CROWD_ROLE_ARN: ${{ secrets.LF_PRODUCTION_CLUSTER_ROLE_ARN }} - AWS_ACCESS_KEY_ID: ${{ secrets.LF_AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.LF_AWS_SECRET_ACCESS_KEY }} - AWS_REGION: ${{ secrets.LF_AWS_REGION }} - SLACK_CHANNEL: deploys-lf - SLACK_WEBHOOK: ${{ secrets.LF_PRODUCTION_SLACK_CHANNEL_HOOK }} - -jobs: - build-and-push-search-sync-worker: - runs-on: ubuntu-latest - if: ${{ inputs.deploy_search_sync_worker }} - outputs: - image: ${{ steps.image.outputs.IMAGE }} - defaults: - run: - shell: bash - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/build-docker-image - id: image-builder - with: - image: search-sync-worker - - - name: Set docker image output - id: image - run: echo "IMAGE=${{ steps.image-builder.outputs.image }}" >> $GITHUB_OUTPUT - - build-and-push-search-sync-api: - runs-on: ubuntu-latest - if: ${{ inputs.deploy_search_sync_api }} - outputs: - image: ${{ steps.image.outputs.IMAGE }} - defaults: - run: - shell: bash - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/build-docker-image - id: image-builder - with: - image: search-sync-api - - - name: Set docker image output - id: image - run: echo "IMAGE=${{ steps.image-builder.outputs.image }}" >> $GITHUB_OUTPUT - - build-and-push-integration-sync-worker: - runs-on: ubuntu-latest - if: ${{ inputs.deploy_integration_sync_worker }} - outputs: - image: ${{ steps.image.outputs.IMAGE }} - defaults: - run: - shell: bash - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/build-docker-image - id: image-builder - with: - image: integration-sync-worker - - - name: Set docker image output - id: image - run: echo "IMAGE=${{ steps.image-builder.outputs.image }}" >> $GITHUB_OUTPUT - - build-and-push-webhook-api: - runs-on: ubuntu-latest - if: ${{ inputs.deploy_webhook_api }} - outputs: - image: ${{ steps.image.outputs.IMAGE }} - defaults: - run: - shell: bash - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/build-docker-image - id: image-builder - with: - image: webhook-api - - - name: Set docker image output - id: image - run: echo "IMAGE=${{ steps.image-builder.outputs.image }}" >> $GITHUB_OUTPUT - - build-and-push-automations-worker: - runs-on: ubuntu-latest - if: ${{ inputs.deploy_automations_worker }} - outputs: - image: ${{ steps.image.outputs.IMAGE }} - defaults: - run: - shell: bash - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/build-docker-image - id: image-builder - with: - image: automations-worker - - - name: Set docker image output - id: image - run: echo "IMAGE=${{ steps.image-builder.outputs.image }}" >> $GITHUB_OUTPUT - - build-and-push-emails-worker: - runs-on: ubuntu-latest - if: ${{ inputs.deploy_emails_worker }} - outputs: - image: ${{ steps.image.outputs.IMAGE }} - defaults: - run: - shell: bash - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/build-docker-image - id: image-builder - with: - image: emails-worker - - - name: Set docker image output - id: image - run: echo "IMAGE=${{ steps.image-builder.outputs.image }}" >> $GITHUB_OUTPUT - - build-and-push-script-executor: - runs-on: ubuntu-latest - if: ${{ inputs.deploy_script_executor }} - outputs: - image: ${{ steps.image.outputs.IMAGE }} - defaults: - run: - shell: bash - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/build-docker-image - id: image-builder - with: - image: script-executor - - - name: Set docker image output - id: image - run: echo "IMAGE=${{ steps.image-builder.outputs.image }}" >> $GITHUB_OUTPUT - - deploy-search-sync-worker: - needs: build-and-push-search-sync-worker - runs-on: ubuntu-latest - if: ${{ inputs.deploy_search_sync_worker }} - defaults: - run: - shell: bash - - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/deploy-service - with: - service: search-sync-worker - image: ${{ needs.build-and-push-search-sync-worker.outputs.image }} - cluster: ${{ env.CROWD_CLUSTER }} - - deploy-search-sync-api: - needs: build-and-push-search-sync-api - runs-on: ubuntu-latest - if: ${{ inputs.deploy_search_sync_api }} - defaults: - run: - shell: bash - - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/deploy-service - with: - service: search-sync-api - image: ${{ needs.build-and-push-search-sync-api.outputs.image }} - cluster: ${{ env.CROWD_CLUSTER }} - - deploy-integration-sync-worker: - needs: build-and-push-integration-sync-worker - runs-on: ubuntu-latest - if: ${{ inputs.deploy_integration_sync_worker }} - defaults: - run: - shell: bash - - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/deploy-service - with: - service: integration-sync-worker - image: ${{ needs.build-and-push-integration-sync-worker.outputs.image }} - cluster: ${{ env.CROWD_CLUSTER }} - - deploy-webhook-api: - needs: build-and-push-webhook-api - runs-on: ubuntu-latest - if: ${{ inputs.deploy_webhook_api }} - defaults: - run: - shell: bash - - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/deploy-service - with: - service: webhook-api - image: ${{ needs.build-and-push-webhook-api.outputs.image }} - cluster: ${{ env.CROWD_CLUSTER }} - - deploy-automations-worker: - needs: build-and-push-automations-worker - runs-on: ubuntu-latest - if: ${{ inputs.deploy_automations_worker }} - defaults: - run: - shell: bash - - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/deploy-service - with: - service: automations-worker - image: ${{ needs.build-and-push-automations-worker.outputs.image }} - cluster: ${{ env.CROWD_CLUSTER }} - - deploy-emails-worker: - needs: build-and-push-emails-worker - runs-on: ubuntu-latest - if: ${{ inputs.deploy_emails_worker }} - defaults: - run: - shell: bash - - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/deploy-service - with: - service: emails-worker - image: ${{ needs.build-and-push-emails-worker.outputs.image }} - cluster: ${{ env.CROWD_CLUSTER }} - - deploy-script-executor: - needs: build-and-push-script-executor - runs-on: ubuntu-latest - if: ${{ inputs.deploy_script_executor }} - defaults: - run: - shell: bash - - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/deploy-service - with: - service: script-executor - image: ${{ needs.build-and-push-script-executor.outputs.image }} - cluster: ${{ env.CROWD_CLUSTER }} diff --git a/.github/workflows/lf-production-deploy-original.yaml b/.github/workflows/lf-production-deploy-original.yaml deleted file mode 100644 index 3e5fd30a4a..0000000000 --- a/.github/workflows/lf-production-deploy-original.yaml +++ /dev/null @@ -1,383 +0,0 @@ -name: LF Production Deploy Original - -on: - workflow_dispatch: - inputs: - deploy_api: - description: Deploy api service? - required: true - type: boolean - deploy_job_generator: - description: Deploy job-generator service? - required: true - type: boolean - deploy_nodejs_worker: - description: Deploy nodejs-worker service? - required: true - type: boolean - deploy_discord_ws: - description: Deploy discord-ws service? - required: true - type: boolean - deploy_integration_run_worker: - description: Deploy integration-run-worker service? - required: true - type: boolean - deploy_integration_stream_worker: - description: Deploy integration-stream-worker service? - required: true - type: boolean - deploy_integration_data_worker: - description: Deploy integration-data-worker service? - required: true - type: boolean - deploy_data_sink_worker: - description: Deploy data-sink-worker service? - required: true - type: boolean - deploy_python_worker: - description: Deploy python-worker service? - required: true - type: boolean - deploy_frontend: - description: Deploy frontend? - required: true - type: boolean - -env: - DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} - DOCKERHUB_PASSWORD: ${{ secrets.DOCKERHUB_PASSWORD }} - CROWD_CLUSTER: ${{ secrets.LF_PRODUCTION_CLUSTER_NAME }} - CROWD_ROLE_ARN: ${{ secrets.LF_PRODUCTION_CLUSTER_ROLE_ARN }} - AWS_ACCESS_KEY_ID: ${{ secrets.LF_AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.LF_AWS_SECRET_ACCESS_KEY }} - AWS_REGION: ${{ secrets.LF_AWS_REGION }} - SLACK_CHANNEL: deploys-lf - SLACK_WEBHOOK: ${{ secrets.LF_PRODUCTION_SLACK_CHANNEL_HOOK }} - -jobs: - build-and-push-backend: - runs-on: ubuntu-latest - if: ${{ inputs.deploy_api || inputs.deploy_job_generator || inputs.deploy_nodejs_worker || inputs.deploy_discord_ws }} - outputs: - image: ${{ steps.image.outputs.IMAGE }} - defaults: - run: - shell: bash - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/build-docker-image - id: image-builder - with: - image: backend - - - name: Set docker image output - id: image - run: echo "IMAGE=${{ steps.image-builder.outputs.image }}" >> $GITHUB_OUTPUT - - build-and-push-integration-run-worker: - runs-on: ubuntu-latest - if: ${{ inputs.deploy_integration_run_worker }} - outputs: - image: ${{ steps.image.outputs.IMAGE }} - defaults: - run: - shell: bash - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/build-docker-image - id: image-builder - with: - image: integration-run-worker - - - name: Set docker image output - id: image - run: echo "IMAGE=${{ steps.image-builder.outputs.image }}" >> $GITHUB_OUTPUT - - build-and-push-integration-stream-worker: - runs-on: ubuntu-latest - if: ${{ inputs.deploy_integration_stream_worker }} - outputs: - image: ${{ steps.image.outputs.IMAGE }} - defaults: - run: - shell: bash - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/build-docker-image - id: image-builder - with: - image: integration-stream-worker - - - name: Set docker image output - id: image - run: echo "IMAGE=${{ steps.image-builder.outputs.image }}" >> $GITHUB_OUTPUT - - build-and-push-integration-data-worker: - runs-on: ubuntu-latest - if: ${{ inputs.deploy_integration_data_worker }} - outputs: - image: ${{ steps.image.outputs.IMAGE }} - defaults: - run: - shell: bash - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/build-docker-image - id: image-builder - with: - image: integration-data-worker - - - name: Set docker image output - id: image - run: echo "IMAGE=${{ steps.image-builder.outputs.image }}" >> $GITHUB_OUTPUT - - build-and-push-data-sink-worker: - runs-on: ubuntu-latest - if: ${{ inputs.deploy_data_sink_worker }} - outputs: - image: ${{ steps.image.outputs.IMAGE }} - defaults: - run: - shell: bash - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/build-docker-image - id: image-builder - with: - image: data-sink-worker - - - name: Set docker image output - id: image - run: echo "IMAGE=${{ steps.image-builder.outputs.image }}" >> $GITHUB_OUTPUT - - build-and-push-frontend: - runs-on: ubuntu-latest - if: ${{ inputs.deploy_frontend }} - outputs: - image: ${{ steps.image.outputs.IMAGE }} - defaults: - run: - shell: bash - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/build-docker-image - id: image-builder - with: - image: frontend - - - name: Set docker image output - id: image - run: echo "IMAGE=${{ steps.image-builder.outputs.image }}" >> $GITHUB_OUTPUT - - build-and-push-python-worker: - runs-on: ubuntu-latest - if: ${{ inputs.deploy_python_worker }} - outputs: - image: ${{ steps.image.outputs.IMAGE }} - defaults: - run: - shell: bash - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/build-docker-image - id: image-builder - with: - image: python-worker - - - name: Set docker image output - id: image - run: echo "IMAGE=${{ steps.image-builder.outputs.image }}" >> $GITHUB_OUTPUT - - deploy-api: - needs: build-and-push-backend - runs-on: ubuntu-latest - if: ${{ inputs.deploy_api }} - defaults: - run: - shell: bash - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/deploy-service - with: - service: api - image: ${{ needs.build-and-push-backend.outputs.image }} - cluster: ${{ env.CROWD_CLUSTER }} - - deploy-nodejs-worker: - needs: build-and-push-backend - runs-on: ubuntu-latest - if: ${{ inputs.deploy_nodejs_worker }} - defaults: - run: - shell: bash - - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/deploy-service - with: - service: nodejs-worker - image: ${{ needs.build-and-push-backend.outputs.image }} - cluster: ${{ env.CROWD_CLUSTER }} - - deploy-discord-ws: - needs: build-and-push-backend - runs-on: ubuntu-latest - if: ${{ inputs.deploy_discord_ws }} - defaults: - run: - shell: bash - - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/deploy-service - with: - service: discord-ws - image: ${{ needs.build-and-push-backend.outputs.image }} - cluster: ${{ env.CROWD_CLUSTER }} - - deploy-job-generator: - needs: build-and-push-backend - runs-on: ubuntu-latest - if: ${{ inputs.deploy_job_generator }} - defaults: - run: - shell: bash - - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/deploy-service - with: - service: job-generator - image: ${{ needs.build-and-push-backend.outputs.image }} - cluster: ${{ env.CROWD_CLUSTER }} - - deploy-integration-run-worker: - needs: build-and-push-integration-run-worker - runs-on: ubuntu-latest - if: ${{ inputs.deploy_integration_run_worker }} - defaults: - run: - shell: bash - - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/deploy-service - with: - service: integration-run-worker - image: ${{ needs.build-and-push-integration-run-worker.outputs.image }} - cluster: ${{ env.CROWD_CLUSTER }} - - deploy-integration-stream-worker: - needs: build-and-push-integration-stream-worker - runs-on: ubuntu-latest - if: ${{ inputs.deploy_integration_stream_worker }} - defaults: - run: - shell: bash - - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/deploy-service - with: - service: integration-stream-worker - image: ${{ needs.build-and-push-integration-stream-worker.outputs.image }} - cluster: ${{ env.CROWD_CLUSTER }} - - deploy-integration-data-worker: - needs: build-and-push-integration-data-worker - runs-on: ubuntu-latest - if: ${{ inputs.deploy_integration_data_worker }} - defaults: - run: - shell: bash - - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/deploy-service - with: - service: integration-data-worker - image: ${{ needs.build-and-push-integration-data-worker.outputs.image }} - cluster: ${{ env.CROWD_CLUSTER }} - - deploy-data-sink-worker: - needs: build-and-push-data-sink-worker - runs-on: ubuntu-latest - if: ${{ inputs.deploy_data_sink_worker }} - defaults: - run: - shell: bash - - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/deploy-service - with: - service: data-sink-worker - image: ${{ needs.build-and-push-data-sink-worker.outputs.image }} - cluster: ${{ env.CROWD_CLUSTER }} - - deploy-frontend: - needs: build-and-push-frontend - runs-on: ubuntu-latest - if: ${{ inputs.deploy_frontend }} - defaults: - run: - shell: bash - - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/deploy-service - with: - service: frontend - image: ${{ needs.build-and-push-frontend.outputs.image }} - cluster: ${{ env.CROWD_CLUSTER }} - - deploy-python-worker: - needs: build-and-push-python-worker - runs-on: ubuntu-latest - if: ${{ inputs.deploy_python_worker }} - defaults: - run: - shell: bash - - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/deploy-service - with: - service: python-worker - image: ${{ needs.build-and-push-python-worker.outputs.image }} - cluster: ${{ env.CROWD_CLUSTER }} diff --git a/.github/workflows/lf-production-deploy.yaml b/.github/workflows/lf-production-deploy.yaml new file mode 100644 index 0000000000..8c14834448 --- /dev/null +++ b/.github/workflows/lf-production-deploy.yaml @@ -0,0 +1,27 @@ +name: LF Production Deploy + +on: + workflow_dispatch: + inputs: + services: + description: Space separated list of services to deploy + required: true + +env: + CLOUD_ENV: lf-production + DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} + DOCKERHUB_PASSWORD: ${{ secrets.DOCKERHUB_PASSWORD }} + CROWD_CLUSTER: ${{ secrets.LF_PRODUCTION_CLUSTER_NAME }} + CROWD_ROLE_ARN: ${{ secrets.LF_PRODUCTION_CLUSTER_ROLE_ARN }} + AWS_ACCESS_KEY_ID: ${{ secrets.LF_AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.LF_AWS_SECRET_ACCESS_KEY }} + AWS_REGION: ${{ secrets.LF_AWS_REGION }} + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: ./.github/actions/node/builder + with: + services: ${{ github.event.inputs.services }} diff --git a/.github/workflows/lf-staging-deploy-backend.yaml b/.github/workflows/lf-staging-deploy-backend.yaml index 7cee20ac98..d39f330fbc 100644 --- a/.github/workflows/lf-staging-deploy-backend.yaml +++ b/.github/workflows/lf-staging-deploy-backend.yaml @@ -76,6 +76,8 @@ jobs: service: nodejs-worker image: ${{ needs.build-and-push.outputs.image }} cluster: ${{ env.CROWD_CLUSTER }} + cloud_env: lfx_staging + prioritized: true deploy-job-generator: needs: build-and-push diff --git a/.github/workflows/lf-staging-deploy-cache-worker.yaml b/.github/workflows/lf-staging-deploy-cache-worker.yaml new file mode 100644 index 0000000000..d66f25dab0 --- /dev/null +++ b/.github/workflows/lf-staging-deploy-cache-worker.yaml @@ -0,0 +1,60 @@ +name: LF Staging Deploy Cache Worker + +on: + push: + branches: + - "lf-staging/**" + - "lf-staging-**" + paths: + - "services/libs/**" + - "services/apps/cache_worker/**" + +env: + DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} + DOCKERHUB_PASSWORD: ${{ secrets.DOCKERHUB_PASSWORD }} + CROWD_CLUSTER: ${{ secrets.LF_STAGING_CLUSTER_NAME }} + CROWD_ROLE_ARN: ${{ secrets.LF_STAGING_CLUSTER_ROLE_ARN }} + AWS_ACCESS_KEY_ID: ${{ secrets.LF_AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.LF_AWS_SECRET_ACCESS_KEY }} + AWS_REGION: ${{ secrets.LF_AWS_REGION }} + SLACK_CHANNEL: deploys-lf-staging + SLACK_WEBHOOK: ${{ secrets.LF_STAGING_SLACK_CHANNEL_HOOK }} + +jobs: + build-and-push: + runs-on: ubuntu-latest + outputs: + image: ${{ steps.image.outputs.IMAGE }} + defaults: + run: + shell: bash + + steps: + - name: Check out repository code + uses: actions/checkout@v2 + + - uses: ./.github/actions/build-docker-image + id: image-builder + with: + image: cache-worker + + - name: Set docker image output + id: image + run: echo "IMAGE=${{ steps.image-builder.outputs.image }}" >> $GITHUB_OUTPUT + + deploy-cache-worker: + needs: build-and-push + runs-on: ubuntu-latest + defaults: + run: + shell: bash + + steps: + - name: Check out repository code + uses: actions/checkout@v2 + + - uses: ./.github/actions/deploy-service + with: + service: cache-worker + image: ${{ needs.build-and-push.outputs.image }} + cluster: ${{ env.CROWD_CLUSTER }} diff --git a/.github/workflows/lf-staging-deploy-data-sink-worker.yaml b/.github/workflows/lf-staging-deploy-data-sink-worker.yaml index 3aa92424ba..6dabe492a4 100644 --- a/.github/workflows/lf-staging-deploy-data-sink-worker.yaml +++ b/.github/workflows/lf-staging-deploy-data-sink-worker.yaml @@ -58,3 +58,5 @@ jobs: service: data-sink-worker image: ${{ needs.build-and-push.outputs.image }} cluster: ${{ env.CROWD_CLUSTER }} + cloud_env: lfx_staging + prioritized: true diff --git a/.github/workflows/lf-staging-deploy-entity-merging-worker.yml b/.github/workflows/lf-staging-deploy-entity-merging-worker.yml new file mode 100644 index 0000000000..9f507013be --- /dev/null +++ b/.github/workflows/lf-staging-deploy-entity-merging-worker.yml @@ -0,0 +1,61 @@ +name: LF Staging Deploy Entity Merging Worker + +on: + push: + branches: + - 'lf-staging/**' + - 'lf-staging-**' + paths: + - 'services/libs/**' + - 'services/apps/entity_merging_worker/**' + +env: + DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} + DOCKERHUB_PASSWORD: ${{ secrets.DOCKERHUB_PASSWORD }} + CROWD_CLUSTER: ${{ secrets.LF_STAGING_CLUSTER_NAME }} + CROWD_ROLE_ARN: ${{ secrets.LF_STAGING_CLUSTER_ROLE_ARN }} + AWS_ACCESS_KEY_ID: ${{ secrets.LF_AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.LF_AWS_SECRET_ACCESS_KEY }} + AWS_REGION: ${{ secrets.LF_AWS_REGION }} + SLACK_CHANNEL: deploys-lf-staging + SLACK_WEBHOOK: ${{ secrets.LF_STAGING_SLACK_CHANNEL_HOOK }} + +jobs: + build-and-push: + runs-on: ubuntu-latest + outputs: + image: ${{ steps.image.outputs.IMAGE }} + defaults: + run: + shell: bash + + steps: + - name: Check out repository code + uses: actions/checkout@v2 + + - uses: ./.github/actions/build-docker-image + id: image-builder + with: + image: entity-merging-worker + + - name: Set docker image output + id: image + run: echo "IMAGE=${{ steps.image-builder.outputs.image }}" >> $GITHUB_OUTPUT + + deploy-entity-merging-worker: + needs: build-and-push + runs-on: ubuntu-latest + defaults: + run: + shell: bash + + steps: + - name: Check out repository code + uses: actions/checkout@v2 + + - uses: ./.github/actions/deploy-service + with: + service: entity-merging-worker + image: ${{ needs.build-and-push.outputs.image }} + cluster: ${{ env.CROWD_CLUSTER }} + diff --git a/.github/workflows/lf-staging-deploy-integration-data-worker.yaml b/.github/workflows/lf-staging-deploy-integration-data-worker.yaml index a059404c0c..74325f88d6 100644 --- a/.github/workflows/lf-staging-deploy-integration-data-worker.yaml +++ b/.github/workflows/lf-staging-deploy-integration-data-worker.yaml @@ -58,3 +58,5 @@ jobs: service: integration-data-worker image: ${{ needs.build-and-push.outputs.image }} cluster: ${{ env.CROWD_CLUSTER }} + cloud_env: lfx_staging + prioritized: true diff --git a/.github/workflows/lf-staging-deploy-integration-run-worker.yaml b/.github/workflows/lf-staging-deploy-integration-run-worker.yaml index c26285a4e8..a18be6d287 100644 --- a/.github/workflows/lf-staging-deploy-integration-run-worker.yaml +++ b/.github/workflows/lf-staging-deploy-integration-run-worker.yaml @@ -58,3 +58,5 @@ jobs: service: integration-run-worker image: ${{ needs.build-and-push.outputs.image }} cluster: ${{ env.CROWD_CLUSTER }} + cloud_env: lfx_staging + prioritized: true diff --git a/.github/workflows/lf-staging-deploy-integration-stream-worker.yaml b/.github/workflows/lf-staging-deploy-integration-stream-worker.yaml index e69c76ced3..1bc1cbb0fc 100644 --- a/.github/workflows/lf-staging-deploy-integration-stream-worker.yaml +++ b/.github/workflows/lf-staging-deploy-integration-stream-worker.yaml @@ -58,3 +58,5 @@ jobs: service: integration-stream-worker image: ${{ needs.build-and-push.outputs.image }} cluster: ${{ env.CROWD_CLUSTER }} + cloud_env: lfx_staging + prioritized: true diff --git a/.github/workflows/lf-staging-deploy-members-enrichment-worker.yaml b/.github/workflows/lf-staging-deploy-members-enrichment-worker.yaml new file mode 100644 index 0000000000..72fbf11d2d --- /dev/null +++ b/.github/workflows/lf-staging-deploy-members-enrichment-worker.yaml @@ -0,0 +1,60 @@ +name: LF Staging Deploy Members Enrichment Worker + +on: + push: + branches: + - 'lf-staging/**' + - 'lf-staging-**' + paths: + - 'services/libs/**' + - 'services/apps/premium/members_enrichment_worker/**' + +env: + DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} + DOCKERHUB_PASSWORD: ${{ secrets.DOCKERHUB_PASSWORD }} + CROWD_CLUSTER: ${{ secrets.LF_STAGING_CLUSTER_NAME }} + CROWD_ROLE_ARN: ${{ secrets.LF_STAGING_CLUSTER_ROLE_ARN }} + AWS_ACCESS_KEY_ID: ${{ secrets.LF_AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.LF_AWS_SECRET_ACCESS_KEY }} + AWS_REGION: ${{ secrets.LF_AWS_REGION }} + SLACK_CHANNEL: deploys-lf-staging + SLACK_WEBHOOK: ${{ secrets.LF_STAGING_SLACK_CHANNEL_HOOK }} + +jobs: + build-and-push: + runs-on: ubuntu-latest + outputs: + image: ${{ steps.image.outputs.IMAGE }} + defaults: + run: + shell: bash + + steps: + - name: Check out repository code + uses: actions/checkout@v2 + + - uses: ./.github/actions/build-docker-image + id: image-builder + with: + image: members-enrichment-worker + + - name: Set docker image output + id: image + run: echo "IMAGE=${{ steps.image-builder.outputs.image }}" >> $GITHUB_OUTPUT + + deploy-members-enrichment-worker: + needs: build-and-push + runs-on: ubuntu-latest + defaults: + run: + shell: bash + + steps: + - name: Check out repository code + uses: actions/checkout@v2 + + - uses: ./.github/actions/deploy-service + with: + service: members-enrichment-worker + image: ${{ needs.build-and-push.outputs.image }} + cluster: ${{ env.CROWD_CLUSTER }} diff --git a/.github/workflows/lf-staging-deploy-merge-suggestions-worker.yaml b/.github/workflows/lf-staging-deploy-merge-suggestions-worker.yaml new file mode 100644 index 0000000000..a1fb4a60f2 --- /dev/null +++ b/.github/workflows/lf-staging-deploy-merge-suggestions-worker.yaml @@ -0,0 +1,60 @@ +name: LF Staging Deploy Merge Suggestions Worker + +on: + push: + branches: + - "lf-staging/**" + - "lf-staging-**" + paths: + - "services/libs/**" + - "services/apps/merge_suggestions_worker/**" + +env: + DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} + DOCKERHUB_PASSWORD: ${{ secrets.DOCKERHUB_PASSWORD }} + CROWD_CLUSTER: ${{ secrets.LF_STAGING_CLUSTER_NAME }} + CROWD_ROLE_ARN: ${{ secrets.LF_STAGING_CLUSTER_ROLE_ARN }} + AWS_ACCESS_KEY_ID: ${{ secrets.LF_AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.LF_AWS_SECRET_ACCESS_KEY }} + AWS_REGION: ${{ secrets.LF_AWS_REGION }} + SLACK_CHANNEL: deploys-lf-staging + SLACK_WEBHOOK: ${{ secrets.LF_STAGING_SLACK_CHANNEL_HOOK }} + +jobs: + build-and-push: + runs-on: ubuntu-latest + outputs: + image: ${{ steps.image.outputs.IMAGE }} + defaults: + run: + shell: bash + + steps: + - name: Check out repository code + uses: actions/checkout@v2 + + - uses: ./.github/actions/build-docker-image + id: image-builder + with: + image: merge-suggestions-worker + + - name: Set docker image output + id: image + run: echo "IMAGE=${{ steps.image-builder.outputs.image }}" >> $GITHUB_OUTPUT + + deploy-merge-suggestions-worker: + needs: build-and-push + runs-on: ubuntu-latest + defaults: + run: + shell: bash + + steps: + - name: Check out repository code + uses: actions/checkout@v2 + + - uses: ./.github/actions/deploy-service + with: + service: merge-suggestions-worker + image: ${{ needs.build-and-push.outputs.image }} + cluster: ${{ env.CROWD_CLUSTER }} diff --git a/.github/workflows/lf-staging-deploy-organizations-enrichment-worker.yaml b/.github/workflows/lf-staging-deploy-organizations-enrichment-worker.yaml new file mode 100644 index 0000000000..b0635923c1 --- /dev/null +++ b/.github/workflows/lf-staging-deploy-organizations-enrichment-worker.yaml @@ -0,0 +1,60 @@ +name: LF Staging Deploy Organizations Enrichment Worker + +on: + push: + branches: + - 'lf-staging/**' + - 'lf-staging-**' + paths: + - 'services/libs/**' + - 'services/apps/premium/organizations_enrichment_worker/**' + +env: + DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} + DOCKERHUB_PASSWORD: ${{ secrets.DOCKERHUB_PASSWORD }} + CROWD_CLUSTER: ${{ secrets.LF_STAGING_CLUSTER_NAME }} + CROWD_ROLE_ARN: ${{ secrets.LF_STAGING_CLUSTER_ROLE_ARN }} + AWS_ACCESS_KEY_ID: ${{ secrets.LF_AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.LF_AWS_SECRET_ACCESS_KEY }} + AWS_REGION: ${{ secrets.LF_AWS_REGION }} + SLACK_CHANNEL: deploys-lf-staging + SLACK_WEBHOOK: ${{ secrets.LF_STAGING_SLACK_CHANNEL_HOOK }} + +jobs: + build-and-push: + runs-on: ubuntu-latest + outputs: + image: ${{ steps.image.outputs.IMAGE }} + defaults: + run: + shell: bash + + steps: + - name: Check out repository code + uses: actions/checkout@v2 + + - uses: ./.github/actions/build-docker-image + id: image-builder + with: + image: organizations-enrichment-worker + + - name: Set docker image output + id: image + run: echo "IMAGE=${{ steps.image-builder.outputs.image }}" >> $GITHUB_OUTPUT + + deploy-organizations-enrichment-worker: + needs: build-and-push + runs-on: ubuntu-latest + defaults: + run: + shell: bash + + steps: + - name: Check out repository code + uses: actions/checkout@v2 + + - uses: ./.github/actions/deploy-service + with: + service: organizations-enrichment-worker + image: ${{ needs.build-and-push.outputs.image }} + cluster: ${{ env.CROWD_CLUSTER }} diff --git a/.github/workflows/lf-staging-deploy-profiles-worker.yaml b/.github/workflows/lf-staging-deploy-profiles-worker.yaml new file mode 100644 index 0000000000..71840b25f6 --- /dev/null +++ b/.github/workflows/lf-staging-deploy-profiles-worker.yaml @@ -0,0 +1,60 @@ +name: LF Staging Deploy Profiles Worker + +on: + push: + branches: + - 'lf-staging/**' + - 'lf-staging-**' + paths: + - 'services/libs/**' + - 'services/apps/profiles_worker/**' + +env: + DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} + DOCKERHUB_PASSWORD: ${{ secrets.DOCKERHUB_PASSWORD }} + CROWD_CLUSTER: ${{ secrets.LF_STAGING_CLUSTER_NAME }} + CROWD_ROLE_ARN: ${{ secrets.LF_STAGING_CLUSTER_ROLE_ARN }} + AWS_ACCESS_KEY_ID: ${{ secrets.LF_AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.LF_AWS_SECRET_ACCESS_KEY }} + AWS_REGION: ${{ secrets.LF_AWS_REGION }} + SLACK_CHANNEL: deploys-lf-staging + SLACK_WEBHOOK: ${{ secrets.LF_STAGING_SLACK_CHANNEL_HOOK }} + +jobs: + build-and-push: + runs-on: ubuntu-latest + outputs: + image: ${{ steps.image.outputs.IMAGE }} + defaults: + run: + shell: bash + + steps: + - name: Check out repository code + uses: actions/checkout@v2 + + - uses: ./.github/actions/build-docker-image + id: image-builder + with: + image: profiles-worker + + - name: Set docker image output + id: image + run: echo "IMAGE=${{ steps.image-builder.outputs.image }}" >> $GITHUB_OUTPUT + + deploy-profiles-worker: + needs: build-and-push + runs-on: ubuntu-latest + defaults: + run: + shell: bash + + steps: + - name: Check out repository code + uses: actions/checkout@v2 + + - uses: ./.github/actions/deploy-service + with: + service: profiles-worker + image: ${{ needs.build-and-push.outputs.image }} + cluster: ${{ env.CROWD_CLUSTER }} diff --git a/.github/workflows/lf-staging-deploy-search-sync-worker.yaml b/.github/workflows/lf-staging-deploy-search-sync-worker.yaml index 022c152bd6..391f0a01ab 100644 --- a/.github/workflows/lf-staging-deploy-search-sync-worker.yaml +++ b/.github/workflows/lf-staging-deploy-search-sync-worker.yaml @@ -58,3 +58,5 @@ jobs: service: search-sync-worker image: ${{ needs.build-and-push.outputs.image }} cluster: ${{ env.CROWD_CLUSTER }} + cloud_env: lfx_staging + prioritized: true diff --git a/.github/workflows/lf-staging-deploy.yaml b/.github/workflows/lf-staging-deploy.yaml new file mode 100644 index 0000000000..15162ffb7d --- /dev/null +++ b/.github/workflows/lf-staging-deploy.yaml @@ -0,0 +1,27 @@ +name: LF Staging Deploy + +on: + workflow_dispatch: + inputs: + services: + description: Space separated list of services to deploy + required: true + +env: + CLOUD_ENV: lf-staging + DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} + DOCKERHUB_PASSWORD: ${{ secrets.DOCKERHUB_PASSWORD }} + CROWD_CLUSTER: ${{ secrets.LF_STAGING_CLUSTER_NAME }} + CROWD_ROLE_ARN: ${{ secrets.LF_STAGING_CLUSTER_ROLE_ARN }} + AWS_ACCESS_KEY_ID: ${{ secrets.LF_AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.LF_AWS_SECRET_ACCESS_KEY }} + AWS_REGION: ${{ secrets.LF_AWS_REGION }} + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: ./.github/actions/node/builder + with: + services: ${{ github.event.inputs.services }} diff --git a/.github/workflows/production-deploy-new.yaml b/.github/workflows/production-deploy-new.yaml deleted file mode 100644 index 25baf153c2..0000000000 --- a/.github/workflows/production-deploy-new.yaml +++ /dev/null @@ -1,318 +0,0 @@ -name: Production Deploy New - -on: - workflow_dispatch: - inputs: - deploy_search_sync_worker: - description: Deploy search-sync-worker service? - required: true - type: boolean - deploy_search_sync_api: - description: Deploy search-sync-api service? - required: true - type: boolean - deploy_integration_sync_worker: - description: Deploy integration-sync-worker service? - required: true - type: boolean - deploy_webhook_api: - description: Deploy webhook-api service? - required: true - type: boolean - deploy_automations_worker: - description: Deploy automations-worker service? - required: true - type: boolean - deploy_emails_worker: - description: Deploy emails-worker service? - required: true - type: boolean - deploy_script_executor: - description: Deploy script-executor service? - required: true - type: boolean - -env: - DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} - DOCKERHUB_PASSWORD: ${{ secrets.DOCKERHUB_PASSWORD }} - CROWD_CLUSTER: ${{ secrets.PRODUCTION_CLUSTER_NAME }} - CROWD_ROLE_ARN: ${{ secrets.PRODUCTION_CLUSTER_ROLE_ARN }} - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - AWS_REGION: ${{ secrets.AWS_REGION }} - SLACK_CHANNEL: deploys - SLACK_WEBHOOK: ${{ secrets.PRODUCTION_SLACK_CHANNEL_HOOK }} - -jobs: - build-and-push-search-sync-worker: - runs-on: ubuntu-latest - if: ${{ inputs.deploy_search_sync_worker }} - outputs: - image: ${{ steps.image.outputs.IMAGE }} - defaults: - run: - shell: bash - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/build-docker-image - id: image-builder - with: - image: search-sync-worker - - - name: Set docker image output - id: image - run: echo "IMAGE=${{ steps.image-builder.outputs.image }}" >> $GITHUB_OUTPUT - - build-and-push-search-sync-api: - runs-on: ubuntu-latest - if: ${{ inputs.deploy_search_sync_api }} - outputs: - image: ${{ steps.image.outputs.IMAGE }} - defaults: - run: - shell: bash - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/build-docker-image - id: image-builder - with: - image: search-sync-api - - - name: Set docker image output - id: image - run: echo "IMAGE=${{ steps.image-builder.outputs.image }}" >> $GITHUB_OUTPUT - - build-and-push-integration-sync-worker: - runs-on: ubuntu-latest - if: ${{ inputs.deploy_integration_sync_worker }} - outputs: - image: ${{ steps.image.outputs.IMAGE }} - defaults: - run: - shell: bash - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/build-docker-image - id: image-builder - with: - image: integration-sync-worker - - - name: Set docker image output - id: image - run: echo "IMAGE=${{ steps.image-builder.outputs.image }}" >> $GITHUB_OUTPUT - - build-and-push-webhook-api: - runs-on: ubuntu-latest - if: ${{ inputs.deploy_webhook_api }} - outputs: - image: ${{ steps.image.outputs.IMAGE }} - defaults: - run: - shell: bash - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/build-docker-image - id: image-builder - with: - image: webhook-api - - - name: Set docker image output - id: image - run: echo "IMAGE=${{ steps.image-builder.outputs.image }}" >> $GITHUB_OUTPUT - - build-and-push-automations-worker: - runs-on: ubuntu-latest - if: ${{ inputs.deploy_automations_worker }} - outputs: - image: ${{ steps.image.outputs.IMAGE }} - defaults: - run: - shell: bash - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/build-docker-image - id: image-builder - with: - image: automations-worker - - - name: Set docker image output - id: image - run: echo "IMAGE=${{ steps.image-builder.outputs.image }}" >> $GITHUB_OUTPUT - - build-and-push-emails-worker: - runs-on: ubuntu-latest - if: ${{ inputs.deploy_emails_worker }} - outputs: - image: ${{ steps.image.outputs.IMAGE }} - defaults: - run: - shell: bash - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/build-docker-image - id: image-builder - with: - image: emails-worker - - - name: Set docker image output - id: image - run: echo "IMAGE=${{ steps.image-builder.outputs.image }}" >> $GITHUB_OUTPUT - - build-and-push-script-executor: - runs-on: ubuntu-latest - if: ${{ inputs.deploy_script_executor }} - outputs: - image: ${{ steps.image.outputs.IMAGE }} - defaults: - run: - shell: bash - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/build-docker-image - id: image-builder - with: - image: script-executor - - - name: Set docker image output - id: image - run: echo "IMAGE=${{ steps.image-builder.outputs.image }}" >> $GITHUB_OUTPUT - - deploy-search-sync-worker: - needs: build-and-push-search-sync-worker - runs-on: ubuntu-latest - if: ${{ inputs.deploy_search_sync_worker }} - defaults: - run: - shell: bash - - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/deploy-service - with: - service: search-sync-worker - image: ${{ needs.build-and-push-search-sync-worker.outputs.image }} - cluster: ${{ env.CROWD_CLUSTER }} - - deploy-search-sync-api: - needs: build-and-push-search-sync-api - runs-on: ubuntu-latest - if: ${{ inputs.deploy_search_sync_api }} - defaults: - run: - shell: bash - - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/deploy-service - with: - service: search-sync-api - image: ${{ needs.build-and-push-search-sync-api.outputs.image }} - cluster: ${{ env.CROWD_CLUSTER }} - - deploy-integration-sync-worker: - needs: build-and-push-integration-sync-worker - runs-on: ubuntu-latest - if: ${{ inputs.deploy_integration_sync_worker }} - defaults: - run: - shell: bash - - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/deploy-service - with: - service: integration-sync-worker - image: ${{ needs.build-and-push-integration-sync-worker.outputs.image }} - cluster: ${{ env.CROWD_CLUSTER }} - - deploy-webhook-api: - needs: build-and-push-webhook-api - runs-on: ubuntu-latest - if: ${{ inputs.deploy_webhook_api }} - defaults: - run: - shell: bash - - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/deploy-service - with: - service: webhook-api - image: ${{ needs.build-and-push-webhook-api.outputs.image }} - cluster: ${{ env.CROWD_CLUSTER }} - - deploy-automations-worker: - needs: build-and-push-automations-worker - runs-on: ubuntu-latest - if: ${{ inputs.deploy_automations_worker }} - defaults: - run: - shell: bash - - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/deploy-service - with: - service: automations-worker - image: ${{ needs.build-and-push-automations-worker.outputs.image }} - cluster: ${{ env.CROWD_CLUSTER }} - - deploy-emails-worker: - needs: build-and-push-emails-worker - runs-on: ubuntu-latest - if: ${{ inputs.deploy_emails_worker }} - defaults: - run: - shell: bash - - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/deploy-service - with: - service: emails-worker - image: ${{ needs.build-and-push-emails-worker.outputs.image }} - cluster: ${{ env.CROWD_CLUSTER }} - - deploy-script-executor: - needs: build-and-push-script-executor - runs-on: ubuntu-latest - if: ${{ inputs.deploy_script_executor }} - defaults: - run: - shell: bash - - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/deploy-service - with: - service: script-executor - image: ${{ needs.build-and-push-script-executor.outputs.image }} - cluster: ${{ env.CROWD_CLUSTER }} diff --git a/.github/workflows/production-deploy-original.yaml b/.github/workflows/production-deploy-original.yaml deleted file mode 100644 index 195cf84c20..0000000000 --- a/.github/workflows/production-deploy-original.yaml +++ /dev/null @@ -1,383 +0,0 @@ -name: Production Deploy Original - -on: - workflow_dispatch: - inputs: - deploy_api: - description: Deploy api service? - required: true - type: boolean - deploy_job_generator: - description: Deploy job-generator service? - required: true - type: boolean - deploy_nodejs_worker: - description: Deploy nodejs-worker service? - required: true - type: boolean - deploy_discord_ws: - description: Deploy discord-ws service? - required: true - type: boolean - deploy_integration_run_worker: - description: Deploy integration-run-worker service? - required: true - type: boolean - deploy_integration_stream_worker: - description: Deploy integration-stream-worker service? - required: true - type: boolean - deploy_integration_data_worker: - description: Deploy integration-data-worker service? - required: true - type: boolean - deploy_data_sink_worker: - description: Deploy data-sink-worker service? - required: true - type: boolean - deploy_python_worker: - description: Deploy python-worker service? - required: true - type: boolean - deploy_frontend: - description: Deploy frontend? - required: true - type: boolean - -env: - DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} - DOCKERHUB_PASSWORD: ${{ secrets.DOCKERHUB_PASSWORD }} - CROWD_CLUSTER: ${{ secrets.PRODUCTION_CLUSTER_NAME }} - CROWD_ROLE_ARN: ${{ secrets.PRODUCTION_CLUSTER_ROLE_ARN }} - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - AWS_REGION: ${{ secrets.AWS_REGION }} - SLACK_CHANNEL: deploys - SLACK_WEBHOOK: ${{ secrets.PRODUCTION_SLACK_CHANNEL_HOOK }} - -jobs: - build-and-push-backend: - runs-on: ubuntu-latest - if: ${{ inputs.deploy_api || inputs.deploy_job_generator || inputs.deploy_nodejs_worker || inputs.deploy_discord_ws }} - outputs: - image: ${{ steps.image.outputs.IMAGE }} - defaults: - run: - shell: bash - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/build-docker-image - id: image-builder - with: - image: backend - - - name: Set docker image output - id: image - run: echo "IMAGE=${{ steps.image-builder.outputs.image }}" >> $GITHUB_OUTPUT - - build-and-push-integration-run-worker: - runs-on: ubuntu-latest - if: ${{ inputs.deploy_integration_run_worker }} - outputs: - image: ${{ steps.image.outputs.IMAGE }} - defaults: - run: - shell: bash - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/build-docker-image - id: image-builder - with: - image: integration-run-worker - - - name: Set docker image output - id: image - run: echo "IMAGE=${{ steps.image-builder.outputs.image }}" >> $GITHUB_OUTPUT - - build-and-push-integration-stream-worker: - runs-on: ubuntu-latest - if: ${{ inputs.deploy_integration_stream_worker }} - outputs: - image: ${{ steps.image.outputs.IMAGE }} - defaults: - run: - shell: bash - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/build-docker-image - id: image-builder - with: - image: integration-stream-worker - - - name: Set docker image output - id: image - run: echo "IMAGE=${{ steps.image-builder.outputs.image }}" >> $GITHUB_OUTPUT - - build-and-push-integration-data-worker: - runs-on: ubuntu-latest - if: ${{ inputs.deploy_integration_data_worker }} - outputs: - image: ${{ steps.image.outputs.IMAGE }} - defaults: - run: - shell: bash - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/build-docker-image - id: image-builder - with: - image: integration-data-worker - - - name: Set docker image output - id: image - run: echo "IMAGE=${{ steps.image-builder.outputs.image }}" >> $GITHUB_OUTPUT - - build-and-push-data-sink-worker: - runs-on: ubuntu-latest - if: ${{ inputs.deploy_data_sink_worker }} - outputs: - image: ${{ steps.image.outputs.IMAGE }} - defaults: - run: - shell: bash - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/build-docker-image - id: image-builder - with: - image: data-sink-worker - - - name: Set docker image output - id: image - run: echo "IMAGE=${{ steps.image-builder.outputs.image }}" >> $GITHUB_OUTPUT - - build-and-push-frontend: - runs-on: ubuntu-latest - if: ${{ inputs.deploy_frontend }} - outputs: - image: ${{ steps.image.outputs.IMAGE }} - defaults: - run: - shell: bash - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/build-docker-image - id: image-builder - with: - image: frontend - - - name: Set docker image output - id: image - run: echo "IMAGE=${{ steps.image-builder.outputs.image }}" >> $GITHUB_OUTPUT - - build-and-push-python-worker: - runs-on: ubuntu-latest - if: ${{ inputs.deploy_python_worker }} - outputs: - image: ${{ steps.image.outputs.IMAGE }} - defaults: - run: - shell: bash - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/build-docker-image - id: image-builder - with: - image: python-worker - - - name: Set docker image output - id: image - run: echo "IMAGE=${{ steps.image-builder.outputs.image }}" >> $GITHUB_OUTPUT - - deploy-api: - needs: build-and-push-backend - runs-on: ubuntu-latest - if: ${{ inputs.deploy_api }} - defaults: - run: - shell: bash - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/deploy-service - with: - service: api - image: ${{ needs.build-and-push-backend.outputs.image }} - cluster: ${{ env.CROWD_CLUSTER }} - - deploy-nodejs-worker: - needs: build-and-push-backend - runs-on: ubuntu-latest - if: ${{ inputs.deploy_nodejs_worker }} - defaults: - run: - shell: bash - - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/deploy-service - with: - service: nodejs-worker - image: ${{ needs.build-and-push-backend.outputs.image }} - cluster: ${{ env.CROWD_CLUSTER }} - - deploy-discord-ws: - needs: build-and-push-backend - runs-on: ubuntu-latest - if: ${{ inputs.deploy_discord_ws }} - defaults: - run: - shell: bash - - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/deploy-service - with: - service: discord-ws - image: ${{ needs.build-and-push-backend.outputs.image }} - cluster: ${{ env.CROWD_CLUSTER }} - - deploy-job-generator: - needs: build-and-push-backend - runs-on: ubuntu-latest - if: ${{ inputs.deploy_job_generator }} - defaults: - run: - shell: bash - - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/deploy-service - with: - service: job-generator - image: ${{ needs.build-and-push-backend.outputs.image }} - cluster: ${{ env.CROWD_CLUSTER }} - - deploy-integration-run-worker: - needs: build-and-push-integration-run-worker - runs-on: ubuntu-latest - if: ${{ inputs.deploy_integration_run_worker }} - defaults: - run: - shell: bash - - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/deploy-service - with: - service: integration-run-worker - image: ${{ needs.build-and-push-integration-run-worker.outputs.image }} - cluster: ${{ env.CROWD_CLUSTER }} - - deploy-integration-stream-worker: - needs: build-and-push-integration-stream-worker - runs-on: ubuntu-latest - if: ${{ inputs.deploy_integration_stream_worker }} - defaults: - run: - shell: bash - - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/deploy-service - with: - service: integration-stream-worker - image: ${{ needs.build-and-push-integration-stream-worker.outputs.image }} - cluster: ${{ env.CROWD_CLUSTER }} - - deploy-integration-data-worker: - needs: build-and-push-integration-data-worker - runs-on: ubuntu-latest - if: ${{ inputs.deploy_integration_data_worker }} - defaults: - run: - shell: bash - - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/deploy-service - with: - service: integration-data-worker - image: ${{ needs.build-and-push-integration-data-worker.outputs.image }} - cluster: ${{ env.CROWD_CLUSTER }} - - deploy-data-sink-worker: - needs: build-and-push-data-sink-worker - runs-on: ubuntu-latest - if: ${{ inputs.deploy_data_sink_worker }} - defaults: - run: - shell: bash - - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/deploy-service - with: - service: data-sink-worker - image: ${{ needs.build-and-push-data-sink-worker.outputs.image }} - cluster: ${{ env.CROWD_CLUSTER }} - - deploy-frontend: - needs: build-and-push-frontend - runs-on: ubuntu-latest - if: ${{ inputs.deploy_frontend }} - defaults: - run: - shell: bash - - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/deploy-service - with: - service: frontend - image: ${{ needs.build-and-push-frontend.outputs.image }} - cluster: ${{ env.CROWD_CLUSTER }} - - deploy-python-worker: - needs: build-and-push-python-worker - runs-on: ubuntu-latest - if: ${{ inputs.deploy_python_worker }} - defaults: - run: - shell: bash - - steps: - - name: Check out repository code - uses: actions/checkout@v2 - - - uses: ./.github/actions/deploy-service - with: - service: python-worker - image: ${{ needs.build-and-push-python-worker.outputs.image }} - cluster: ${{ env.CROWD_CLUSTER }} diff --git a/.github/workflows/production-deploy.yaml b/.github/workflows/production-deploy.yaml new file mode 100644 index 0000000000..27d3ab0eeb --- /dev/null +++ b/.github/workflows/production-deploy.yaml @@ -0,0 +1,27 @@ +name: Production Deploy + +on: + workflow_dispatch: + inputs: + services: + description: Space separated list of services to deploy + required: true + +env: + CLOUD_ENV: production + DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} + DOCKERHUB_PASSWORD: ${{ secrets.DOCKERHUB_PASSWORD }} + CROWD_CLUSTER: ${{ secrets.PRODUCTION_CLUSTER_NAME }} + CROWD_ROLE_ARN: ${{ secrets.PRODUCTION_CLUSTER_ROLE_ARN }} + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + AWS_REGION: ${{ secrets.AWS_REGION }} + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: ./.github/actions/node/builder + with: + services: ${{ github.event.inputs.services }} diff --git a/.github/workflows/staging-deploy-backend.yaml b/.github/workflows/staging-deploy-backend.yaml index b8c6f73d6d..a71dde5657 100644 --- a/.github/workflows/staging-deploy-backend.yaml +++ b/.github/workflows/staging-deploy-backend.yaml @@ -76,6 +76,8 @@ jobs: service: nodejs-worker image: ${{ needs.build-and-push.outputs.image }} cluster: ${{ env.CROWD_CLUSTER }} + prioritized: true + cloud_env: staging deploy-job-generator: needs: build-and-push diff --git a/.github/workflows/staging-deploy-cache-worker.yaml b/.github/workflows/staging-deploy-cache-worker.yaml new file mode 100644 index 0000000000..ded6bb717d --- /dev/null +++ b/.github/workflows/staging-deploy-cache-worker.yaml @@ -0,0 +1,60 @@ +name: Staging Deploy Cache Worker + +on: + push: + branches: + - "staging/**" + - "staging-**" + paths: + - "services/libs/**" + - "services/apps/cache_worker/**" + +env: + DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} + DOCKERHUB_PASSWORD: ${{ secrets.DOCKERHUB_PASSWORD }} + CROWD_CLUSTER: ${{ secrets.STAGING_CLUSTER_NAME }} + CROWD_ROLE_ARN: ${{ secrets.STAGING_CLUSTER_ROLE_ARN }} + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + AWS_REGION: ${{ secrets.AWS_REGION }} + SLACK_CHANNEL: deploys-staging + SLACK_WEBHOOK: ${{ secrets.STAGING_SLACK_CHANNEL_HOOK }} + +jobs: + build-and-push: + runs-on: ubuntu-latest + outputs: + image: ${{ steps.image.outputs.IMAGE }} + defaults: + run: + shell: bash + + steps: + - name: Check out repository code + uses: actions/checkout@v2 + + - uses: ./.github/actions/build-docker-image + id: image-builder + with: + image: cache-worker + + - name: Set docker image output + id: image + run: echo "IMAGE=${{ steps.image-builder.outputs.image }}" >> $GITHUB_OUTPUT + + deploy-cache-worker: + needs: build-and-push + runs-on: ubuntu-latest + defaults: + run: + shell: bash + + steps: + - name: Check out repository code + uses: actions/checkout@v2 + + - uses: ./.github/actions/deploy-service + with: + service: cache-worker + image: ${{ needs.build-and-push.outputs.image }} + cluster: ${{ env.CROWD_CLUSTER }} diff --git a/.github/workflows/staging-deploy-data-sink-worker.yaml b/.github/workflows/staging-deploy-data-sink-worker.yaml index 3f9e32557e..716aa7d184 100644 --- a/.github/workflows/staging-deploy-data-sink-worker.yaml +++ b/.github/workflows/staging-deploy-data-sink-worker.yaml @@ -58,3 +58,5 @@ jobs: service: data-sink-worker image: ${{ needs.build-and-push.outputs.image }} cluster: ${{ env.CROWD_CLUSTER }} + cloud_env: staging + prioritized: true diff --git a/.github/workflows/staging-deploy-entity-merging-worker.yml b/.github/workflows/staging-deploy-entity-merging-worker.yml new file mode 100644 index 0000000000..03b59b4af0 --- /dev/null +++ b/.github/workflows/staging-deploy-entity-merging-worker.yml @@ -0,0 +1,60 @@ +name: Staging Deploy Entity Merging Worker + +on: + push: + branches: + - 'staging/**' + - 'staging-**' + paths: + - 'services/libs/**' + - 'services/apps/entity_merging_worker/**' + +env: + DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} + DOCKERHUB_PASSWORD: ${{ secrets.DOCKERHUB_PASSWORD }} + CROWD_CLUSTER: ${{ secrets.STAGING_CLUSTER_NAME }} + CROWD_ROLE_ARN: ${{ secrets.STAGING_CLUSTER_ROLE_ARN }} + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + AWS_REGION: ${{ secrets.AWS_REGION }} + SLACK_CHANNEL: deploys-staging + SLACK_WEBHOOK: ${{ secrets.STAGING_SLACK_CHANNEL_HOOK }} + +jobs: + build-and-push: + runs-on: ubuntu-latest + outputs: + image: ${{ steps.image.outputs.IMAGE }} + defaults: + run: + shell: bash + + steps: + - name: Check out repository code + uses: actions/checkout@v2 + + - uses: ./.github/actions/build-docker-image + id: image-builder + with: + image: entity-merging-worker + + - name: Set docker image output + id: image + run: echo "IMAGE=${{ steps.image-builder.outputs.image }}" >> $GITHUB_OUTPUT + + deploy-entity-merging-worker: + needs: build-and-push + runs-on: ubuntu-latest + defaults: + run: + shell: bash + + steps: + - name: Check out repository code + uses: actions/checkout@v2 + + - uses: ./.github/actions/deploy-service + with: + service: entity-merging-worker + image: ${{ needs.build-and-push.outputs.image }} + cluster: ${{ env.CROWD_CLUSTER }} diff --git a/.github/workflows/staging-deploy-integration-data-worker.yaml b/.github/workflows/staging-deploy-integration-data-worker.yaml index 74b9383984..e5a5b5d586 100644 --- a/.github/workflows/staging-deploy-integration-data-worker.yaml +++ b/.github/workflows/staging-deploy-integration-data-worker.yaml @@ -58,3 +58,5 @@ jobs: service: integration-data-worker image: ${{ needs.build-and-push.outputs.image }} cluster: ${{ env.CROWD_CLUSTER }} + cloud_env: staging + prioritized: true diff --git a/.github/workflows/staging-deploy-integration-run-worker.yaml b/.github/workflows/staging-deploy-integration-run-worker.yaml index 2f733da9bd..b066cf936f 100644 --- a/.github/workflows/staging-deploy-integration-run-worker.yaml +++ b/.github/workflows/staging-deploy-integration-run-worker.yaml @@ -58,3 +58,5 @@ jobs: service: integration-run-worker image: ${{ needs.build-and-push.outputs.image }} cluster: ${{ env.CROWD_CLUSTER }} + cloud_env: staging + prioritized: true diff --git a/.github/workflows/staging-deploy-integration-stream-worker.yaml b/.github/workflows/staging-deploy-integration-stream-worker.yaml index d7500f1d3a..bb993f8f7f 100644 --- a/.github/workflows/staging-deploy-integration-stream-worker.yaml +++ b/.github/workflows/staging-deploy-integration-stream-worker.yaml @@ -58,3 +58,5 @@ jobs: service: integration-stream-worker image: ${{ needs.build-and-push.outputs.image }} cluster: ${{ env.CROWD_CLUSTER }} + cloud_env: staging + prioritized: true diff --git a/.github/workflows/staging-deploy-integration-sync-worker.yaml b/.github/workflows/staging-deploy-integration-sync-worker.yaml index e8674313c6..2085a4a796 100644 --- a/.github/workflows/staging-deploy-integration-sync-worker.yaml +++ b/.github/workflows/staging-deploy-integration-sync-worker.yaml @@ -58,3 +58,5 @@ jobs: service: integration-sync-worker image: ${{ needs.build-and-push.outputs.image }} cluster: ${{ env.CROWD_CLUSTER }} + cloud_env: staging + prioritized: true diff --git a/.github/workflows/staging-deploy-members-enrichment-worker.yaml b/.github/workflows/staging-deploy-members-enrichment-worker.yaml new file mode 100644 index 0000000000..d9a19b6039 --- /dev/null +++ b/.github/workflows/staging-deploy-members-enrichment-worker.yaml @@ -0,0 +1,60 @@ +name: Staging Deploy Members Enrichment Worker + +on: + push: + branches: + - 'staging/**' + - 'staging-**' + paths: + - 'services/libs/**' + - 'services/apps/premium/members_enrichment_worker/**' + +env: + DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} + DOCKERHUB_PASSWORD: ${{ secrets.DOCKERHUB_PASSWORD }} + CROWD_CLUSTER: ${{ secrets.STAGING_CLUSTER_NAME }} + CROWD_ROLE_ARN: ${{ secrets.STAGING_CLUSTER_ROLE_ARN }} + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + AWS_REGION: ${{ secrets.AWS_REGION }} + SLACK_CHANNEL: deploys-staging + SLACK_WEBHOOK: ${{ secrets.STAGING_SLACK_CHANNEL_HOOK }} + +jobs: + build-and-push: + runs-on: ubuntu-latest + outputs: + image: ${{ steps.image.outputs.IMAGE }} + defaults: + run: + shell: bash + + steps: + - name: Check out repository code + uses: actions/checkout@v2 + + - uses: ./.github/actions/build-docker-image + id: image-builder + with: + image: members-enrichment-worker + + - name: Set docker image output + id: image + run: echo "IMAGE=${{ steps.image-builder.outputs.image }}" >> $GITHUB_OUTPUT + + deploy-members-enrichment-worker: + needs: build-and-push + runs-on: ubuntu-latest + defaults: + run: + shell: bash + + steps: + - name: Check out repository code + uses: actions/checkout@v2 + + - uses: ./.github/actions/deploy-service + with: + service: members-enrichment-worker + image: ${{ needs.build-and-push.outputs.image }} + cluster: ${{ env.CROWD_CLUSTER }} diff --git a/.github/workflows/staging-deploy-merge-suggestions-worker.yaml b/.github/workflows/staging-deploy-merge-suggestions-worker.yaml new file mode 100644 index 0000000000..190f2dabfa --- /dev/null +++ b/.github/workflows/staging-deploy-merge-suggestions-worker.yaml @@ -0,0 +1,60 @@ +name: Staging Deploy Merge Suggestions Worker + +on: + push: + branches: + - 'staging/**' + - 'staging-**' + paths: + - 'services/libs/**' + - 'services/apps/merge_suggestions_worker/**' + +env: + DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} + DOCKERHUB_PASSWORD: ${{ secrets.DOCKERHUB_PASSWORD }} + CROWD_CLUSTER: ${{ secrets.STAGING_CLUSTER_NAME }} + CROWD_ROLE_ARN: ${{ secrets.STAGING_CLUSTER_ROLE_ARN }} + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + AWS_REGION: ${{ secrets.AWS_REGION }} + SLACK_CHANNEL: deploys-staging + SLACK_WEBHOOK: ${{ secrets.STAGING_SLACK_CHANNEL_HOOK }} + +jobs: + build-and-push: + runs-on: ubuntu-latest + outputs: + image: ${{ steps.image.outputs.IMAGE }} + defaults: + run: + shell: bash + + steps: + - name: Check out repository code + uses: actions/checkout@v2 + + - uses: ./.github/actions/build-docker-image + id: image-builder + with: + image: merge-suggestions-worker + + - name: Set docker image output + id: image + run: echo "IMAGE=${{ steps.image-builder.outputs.image }}" >> $GITHUB_OUTPUT + + deploy-merge-suggestions-worker: + needs: build-and-push + runs-on: ubuntu-latest + defaults: + run: + shell: bash + + steps: + - name: Check out repository code + uses: actions/checkout@v2 + + - uses: ./.github/actions/deploy-service + with: + service: merge-suggestions-worker + image: ${{ needs.build-and-push.outputs.image }} + cluster: ${{ env.CROWD_CLUSTER }} diff --git a/.github/workflows/staging-deploy-organizations-enrichment-worker.yaml b/.github/workflows/staging-deploy-organizations-enrichment-worker.yaml new file mode 100644 index 0000000000..bda1bd1584 --- /dev/null +++ b/.github/workflows/staging-deploy-organizations-enrichment-worker.yaml @@ -0,0 +1,60 @@ +name: Staging Deploy Organizations Enrichment Worker + +on: + push: + branches: + - 'staging/**' + - 'staging-**' + paths: + - 'services/libs/**' + - 'services/apps/premium/organizations_enrichment_worker/**' + +env: + DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} + DOCKERHUB_PASSWORD: ${{ secrets.DOCKERHUB_PASSWORD }} + CROWD_CLUSTER: ${{ secrets.STAGING_CLUSTER_NAME }} + CROWD_ROLE_ARN: ${{ secrets.STAGING_CLUSTER_ROLE_ARN }} + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + AWS_REGION: ${{ secrets.AWS_REGION }} + SLACK_CHANNEL: deploys-staging + SLACK_WEBHOOK: ${{ secrets.STAGING_SLACK_CHANNEL_HOOK }} + +jobs: + build-and-push: + runs-on: ubuntu-latest + outputs: + image: ${{ steps.image.outputs.IMAGE }} + defaults: + run: + shell: bash + + steps: + - name: Check out repository code + uses: actions/checkout@v2 + + - uses: ./.github/actions/build-docker-image + id: image-builder + with: + image: organizations-enrichment-worker + + - name: Set docker image output + id: image + run: echo "IMAGE=${{ steps.image-builder.outputs.image }}" >> $GITHUB_OUTPUT + + deploy-organizations-enrichment-worker: + needs: build-and-push + runs-on: ubuntu-latest + defaults: + run: + shell: bash + + steps: + - name: Check out repository code + uses: actions/checkout@v2 + + - uses: ./.github/actions/deploy-service + with: + service: organizations-enrichment-worker + image: ${{ needs.build-and-push.outputs.image }} + cluster: ${{ env.CROWD_CLUSTER }} diff --git a/.github/workflows/staging-deploy-profiles-worker.yaml b/.github/workflows/staging-deploy-profiles-worker.yaml new file mode 100644 index 0000000000..871289b851 --- /dev/null +++ b/.github/workflows/staging-deploy-profiles-worker.yaml @@ -0,0 +1,60 @@ +name: Staging Deploy Profiles Worker + +on: + push: + branches: + - 'staging/**' + - 'staging-**' + paths: + - 'services/libs/**' + - 'services/apps/profiles_worker/**' + +env: + DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} + DOCKERHUB_PASSWORD: ${{ secrets.DOCKERHUB_PASSWORD }} + CROWD_CLUSTER: ${{ secrets.STAGING_CLUSTER_NAME }} + CROWD_ROLE_ARN: ${{ secrets.STAGING_CLUSTER_ROLE_ARN }} + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + AWS_REGION: ${{ secrets.AWS_REGION }} + SLACK_CHANNEL: deploys-staging + SLACK_WEBHOOK: ${{ secrets.STAGING_SLACK_CHANNEL_HOOK }} + +jobs: + build-and-push: + runs-on: ubuntu-latest + outputs: + image: ${{ steps.image.outputs.IMAGE }} + defaults: + run: + shell: bash + + steps: + - name: Check out repository code + uses: actions/checkout@v2 + + - uses: ./.github/actions/build-docker-image + id: image-builder + with: + image: profiles-worker + + - name: Set docker image output + id: image + run: echo "IMAGE=${{ steps.image-builder.outputs.image }}" >> $GITHUB_OUTPUT + + deploy-profiles-worker: + needs: build-and-push + runs-on: ubuntu-latest + defaults: + run: + shell: bash + + steps: + - name: Check out repository code + uses: actions/checkout@v2 + + - uses: ./.github/actions/deploy-service + with: + service: profiles-worker + image: ${{ needs.build-and-push.outputs.image }} + cluster: ${{ env.CROWD_CLUSTER }} diff --git a/.github/workflows/staging-deploy-search-sync-worker.yaml b/.github/workflows/staging-deploy-search-sync-worker.yaml index 21e59a4da7..d74c4cbd36 100644 --- a/.github/workflows/staging-deploy-search-sync-worker.yaml +++ b/.github/workflows/staging-deploy-search-sync-worker.yaml @@ -58,3 +58,5 @@ jobs: service: search-sync-worker image: ${{ needs.build-and-push.outputs.image }} cluster: ${{ env.CROWD_CLUSTER }} + cloud_env: staging + prioritized: true diff --git a/.github/workflows/staging-deploy.yaml b/.github/workflows/staging-deploy.yaml new file mode 100644 index 0000000000..ac8f497d23 --- /dev/null +++ b/.github/workflows/staging-deploy.yaml @@ -0,0 +1,27 @@ +name: Staging Deploy + +on: + workflow_dispatch: + inputs: + services: + description: Space separated list of services to deploy + required: true + +env: + CLOUD_ENV: staging + DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} + DOCKERHUB_PASSWORD: ${{ secrets.DOCKERHUB_PASSWORD }} + CROWD_CLUSTER: ${{ secrets.STAGING_CLUSTER_NAME }} + CROWD_ROLE_ARN: ${{ secrets.STAGING_CLUSTER_ROLE_ARN }} + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + AWS_REGION: ${{ secrets.AWS_REGION }} + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: ./.github/actions/node/builder + with: + services: ${{ github.event.inputs.services }} diff --git a/.gitignore b/.gitignore index fc6c23bc76..c45d95311e 100644 --- a/.gitignore +++ b/.gitignore @@ -51,4 +51,4 @@ docker/volume services/libs/*/dist -**/.cubestore \ No newline at end of file +**/.cubestore diff --git a/README.md b/README.md index cf0bc0deeb..ab84a26079 100644 --- a/README.md +++ b/README.md @@ -75,7 +75,7 @@ Our cloud version is a fast, easy, and free ### Self-hosted version -To get started with self-hosting, take a look at our [self-hosting docs](https://docs.crowd.dev/docs/getting-started-with-self-hosting). +To get started with self-hosting, take a look at our [self-hosting docs](https://docs.crowd.dev/docs/technical-docs/self-hosting). #### Deployment with Kubernetes @@ -83,7 +83,7 @@ Our services can be deployed using Kubernetes, as well as a lightweight developm #### Integrations -We currently support all our integrations for self-hosting. For each one of them, you will need to create your own application. You can see the steps for each integration in our [self-hosting integrations guide](https://docs.crowd.dev/docs/self-hosting). +We currently support all our integrations for self-hosting. For each one of them, you will need to create your own application. ### Development environment diff --git a/backend/.env.dist.composed b/backend/.env.dist.composed index 3f548385e6..75bcfb7a47 100644 --- a/backend/.env.dist.composed +++ b/backend/.env.dist.composed @@ -1,8 +1,7 @@ # SQS settings CROWD_SQS_HOST="sqs" CROWD_SQS_ENDPOINT=http://sqs:9324 -CROWD_SQS_NODEJS_WORKER_QUEUE="http://sqs:9324/000000000000/nodejs-worker.fifo" -CROWD_SQS_NODEJS_WORKER_DELAYABLE_QUEUE=http://sqs:9324/000000000000/nodejs-worker +CROWD_SQS_NODEJS_WORKER_QUEUE="http://sqs:9324/000000000000/nodejs-worker-normal.fifo" CROWD_SQS_PYTHON_WORKER_QUEUE="http://sqs:9324/000000000000/python-worker.fifo" # Redis settings diff --git a/backend/.env.dist.local b/backend/.env.dist.local index 7d9a3815a2..d891c9b341 100755 --- a/backend/.env.dist.local +++ b/backend/.env.dist.local @@ -2,6 +2,7 @@ KUBE_MODE=1 CROWD_EDITION=community TENANT_MODE=multi +QUEUE_PRIORITY_LEVEL=normal # API settings CROWD_API_URL=https://localhost/api @@ -15,7 +16,7 @@ CROWD_SQS_HOST=localhost CROWD_SQS_PORT=9324 CROWD_SQS_ENDPOINT=http://localhost:9324 CROWD_SQS_NODEJS_WORKER_QUEUE=http://localhost:9324/000000000000/nodejs-worker.fifo -CROWD_SQS_NODEJS_WORKER_DELAYABLE_QUEUE=http://localhost:9324/000000000000/nodejs-worker +CROWD_SQS_NODEJS_WORKER_PRIORITY_QUEUE=http://localhost:9324/000000000000/nodejs-worker-normal.fifo CROWD_SQS_PYTHON_WORKER_QUEUE=http://localhost:9324/000000000000/python-worker.fifo CROWD_SQS_AWS_ACCOUNT_ID=000000000000 CROWD_SQS_AWS_ACCESS_KEY_ID=x diff --git a/backend/config/custom-environment-variables.json b/backend/config/custom-environment-variables.json index 185844c2f3..cb5a5c318c 100644 --- a/backend/config/custom-environment-variables.json +++ b/backend/config/custom-environment-variables.json @@ -17,7 +17,7 @@ "host": "CROWD_SQS_HOST", "port": "CROWD_SQS_PORT", "nodejsWorkerQueue": "CROWD_SQS_NODEJS_WORKER_QUEUE", - "nodejsWorkerDelayableQueue": "CROWD_SQS_NODEJS_WORKER_DELAYABLE_QUEUE", + "nodejsWorkerPriorityQueue": "CROWD_SQS_NODEJS_WORKER_PRIORITY_QUEUE", "integrationRunWorkerQueue": "CROWD_SQS_INTEGRATION_RUN_WORKER_QUEUE", "pythonWorkerQueue": "CROWD_SQS_PYTHON_WORKER_QUEUE", "aws": { @@ -97,7 +97,9 @@ "stripeSecretKey": "CROWD_STRIPE_SECRET_KEY", "stripWebhookSigningSecret": "CROWD_STRIPE_WEBHOOK_SIGNING_SECRET", "stripeEagleEyePlanProductId": "CROWD_STRIPE_EAGLE_EYE_PLAN_PRODUCT_ID", - "stripeGrowthPlanProductId": "CROWD_STRIPE_GROWTH_PLAN_PRODUCT_ID" + "stripeGrowthPlanProductId": "CROWD_STRIPE_GROWTH_PLAN_PRODUCT_ID", + "stripeScalePlanProductId": "CROWD_STRIPE_SCALE_PLAN_PRODUCT_ID", + "stripeEssentialPlanProductId": "CROWD_STRIPE_ESSENTIAL_PLAN_PRODUCT_ID" }, "twitter": { "clientId": "CROWD_TWITTER_CLIENT_ID", @@ -143,6 +145,10 @@ "clientId": "CROWD_HUBSPOT_CLIENT_ID", "clientSecret": "CROWD_HUBSPOT_CLIENT_SECRET" }, + "reddit": { + "clientId": "CROWD_REDDIT_CLIENT_ID", + "clientSecret": "CROWD_REDDIT_CLIENT_SECRET" + }, "nango": { "url": "CROWD_NANGO_URL", "secretKey": "CROWD_NANGO_SECRET_KEY" diff --git a/backend/config/default.json b/backend/config/default.json index 892ef4358e..1f079577e0 100644 --- a/backend/config/default.json +++ b/backend/config/default.json @@ -38,6 +38,7 @@ }, "github": {}, "stackexchange": {}, + "reddit": {}, "enrichment": {}, "organizationEnrichment": {}, "eagleEye": {}, diff --git a/backend/package.json b/backend/package.json index 9194823c55..441e443ddb 100644 --- a/backend/package.json +++ b/backend/package.json @@ -31,22 +31,23 @@ "format": "prettier --write .", "format-check": "prettier --check .", "tsc-check": "tsc --noEmit", - "script:process-integration": "SERVICE=script TS_NODE_TRANSPILE_ONLY=true node -r tsconfig-paths/register -r ts-node/register src/bin/scripts/process-integration.ts", - "script:process-stream": "SERVICE=script TS_NODE_TRANSPILE_ONLY=true node -r tsconfig-paths/register -r ts-node/register src/bin/scripts/process-stream.ts", "script:continue-run": "SERVICE=script TS_NODE_TRANSPILE_ONLY=true node -r tsconfig-paths/register -r ts-node/register src/bin/scripts/continue-run.ts", "script:change-tenant-plan": "SERVICE=script TS_NODE_TRANSPILE_ONLY=true node -r tsconfig-paths/register -r ts-node/register src/bin/scripts/change-tenant-plan.ts", - "script:process-webhook": "SERVICE=script TS_NODE_TRANSPILE_ONLY=true node -r tsconfig-paths/register -r ts-node/register src/bin/scripts/process-webhook.ts", "script:trigger-webhook": "SERVICE=script TS_NODE_TRANSPILE_ONLY=true node -r tsconfig-paths/register -r ts-node/register src/bin/scripts/trigger-webhook.ts", "script:send-weekly-analytics-email": "SERVICE=script TS_NODE_TRANSPILE_ONLY=true node -r tsconfig-paths/register -r ts-node/register src/bin/scripts/send-weekly-analytics-email.ts", "script:unleash-init": "SERVICE=script TS_NODE_TRANSPILE_ONLY=true node -r tsconfig-paths/register -r ts-node/register src/bin/scripts/unleash-init.ts", "script:enrich-members-organizations": "SERVICE=script TS_NODE_TRANSPILE_ONLY=true node -r tsconfig-paths/register -r ts-node/register src/bin/scripts/enrich-members-and-organizations.ts", "script:enrich-organizations": "SERVICE=script TS_NODE_TRANSPILE_ONLY=true node -r tsconfig-paths/register -r ts-node/register src/bin/scripts/enrich-organizations-synchronous.ts", "script:generate-merge-suggestions": "SERVICE=script TS_NODE_TRANSPILE_ONLY=true node -r tsconfig-paths/register -r ts-node/register src/bin/scripts/generate-merge-suggestions.ts", + "script:generate-merge-suggestions-synchronous": "SERVICE=script TS_NODE_TRANSPILE_ONLY=true node -r tsconfig-paths/register -r ts-node/register src/bin/scripts/generate-merge-suggestions-synchronous.ts", "script:merge-organizations": "SERVICE=script TS_NODE_TRANSPILE_ONLY=true node -r tsconfig-paths/register -r ts-node/register src/bin/scripts/merge-organizations.ts", "script:get-member-enrichment-data": "SERVICE=script TS_NODE_TRANSPILE_ONLY=true node -r tsconfig-paths/register -r ts-node/register src/bin/scripts/get-member-enrichment-data.ts", "script:get-organization-enrichment-data": "SERVICE=script TS_NODE_TRANSPILE_ONLY=true node -r tsconfig-paths/register -r ts-node/register src/bin/scripts/get-organization-enrichment-data.ts", "script:refresh-materialized-views": "SERVICE=script TS_NODE_TRANSPILE_ONLY=true node -r tsconfig-paths/register -r ts-node/register src/bin/scripts/refresh-materialized-views.ts", - "script:unmerge-members": "SERVICE=script TS_NODE_TRANSPILE_ONLY=true node -r tsconfig-paths/register -r ts-node/register src/bin/scripts/unmerge-members.ts" + "script:unmerge-members": "SERVICE=script TS_NODE_TRANSPILE_ONLY=true node -r tsconfig-paths/register -r ts-node/register src/bin/scripts/unmerge-members.ts", + "script:merge-similar-organizations": "SERVICE=script TS_NODE_TRANSPILE_ONLY=true node -r tsconfig-paths/register -r ts-node/register src/bin/scripts/merge-similar-organizations.ts", + "script:cache-dashboard": "SERVICE=script TS_NODE_TRANSPILE_ONLY=true node -r tsconfig-paths/register -r ts-node/register src/bin/scripts/cache-dashboard.ts", + "script:purge-tenants-and-data": "SERVICE=script TS_NODE_TRANSPILE_ONLY=true node -r tsconfig-paths/register -r ts-node/register src/bin/scripts/purge-tenants-and-data.ts" }, "dependencies": { "@aws-sdk/client-comprehend": "^3.159.0", @@ -57,6 +58,7 @@ "@aws-sdk/util-format-url": "^3.226.0", "@crowd/alerting": "file:../services/libs/alerting", "@crowd/common": "file:../services/libs/common", + "@crowd/common_services": "file:../services/libs/common_services", "@crowd/cubejs": "file:../services/libs/cubejs", "@crowd/feature-flags": "file:../services/libs/feature-flags", "@crowd/integrations": "file:../services/libs/integrations", @@ -76,7 +78,7 @@ "@opensearch-project/opensearch": "^1.2.0", "@pm2/io": "^5.0.0", "@sendgrid/eventwebhook": "^7.7.0", - "@sendgrid/mail": "7.2.6", + "@sendgrid/mail": "~8.1.0", "@slack/web-api": "^6.7.2", "@superfaceai/one-sdk": "^1.3.0", "@superfaceai/passport-twitter-oauth2": "^1.0.0", @@ -99,7 +101,7 @@ "cron-time-generator": "^1.3.0", "crowd-sentiment": "^1.1.7", "crypto-js": "^4.1.1", - "discord.js": "^14.7.1", + "discord.js": "^14.14.1", "dotenv": "8.2.0", "dotenv-expand": "^8.0.3", "emoji-dictionary": "^1.0.11", @@ -128,7 +130,7 @@ "passport-google-oauth": "2.0.0", "passport-google-oauth20": "^2.0.0", "passport-slack": "0.0.7", - "peopledatalabs": "^5.0.3", + "peopledatalabs": "~6.1.5", "pg": "^8.7.3", "pm2": "^5.2.0", "sanitize-html": "^2.7.1", diff --git a/backend/src/api/activity/activityQuery.ts b/backend/src/api/activity/activityQuery.ts index cf796ff4ea..78ae30505a 100644 --- a/backend/src/api/activity/activityQuery.ts +++ b/backend/src/api/activity/activityQuery.ts @@ -21,7 +21,15 @@ import track from '../../segment/track' export default async (req, res) => { new PermissionChecker(req).validateHas(Permissions.values.activityRead) - const payload = await new ActivityService(req).query(req.body) + let payload + const newVersion = req.headers['x-crowd-api-version'] === '1' + const service = new ActivityService(req) + + if (newVersion) { + payload = await service.queryV2(req.body) + } else { + payload = await service.query(req.body) + } if (req.body?.filter && Object.keys(req.body.filter).length > 0) { track('Activities Advanced Filter', { ...req.body }, { ...req }) diff --git a/backend/src/api/auth/authSignUp.ts b/backend/src/api/auth/authSignUp.ts index 51faac3a3d..3351c8011c 100644 --- a/backend/src/api/auth/authSignUp.ts +++ b/backend/src/api/auth/authSignUp.ts @@ -1,10 +1,11 @@ import AuthService from '../../services/auth/authService' +import TenantService from '@/services/tenantService' export default async (req, res) => { if (!req.body.acceptedTermsAndPrivacy) { return res.status(422).send({ error: 'Please accept terms of service and privacy policy' }) } - const payload = await AuthService.signup( + const { token, user } = await AuthService.signup( req.body.email, req.body.password, req.body.invitationToken, @@ -15,5 +16,12 @@ export default async (req, res) => { req, ) - return req.responseHandler.success(req, res, payload) + if (!req.body.invitationToken) { + req.currentUser = user + await new TenantService(req).create({ + name: 'temporaryName', + }) + } + + return req.responseHandler.success(req, res, token) } diff --git a/backend/src/api/auth/authSocial.ts b/backend/src/api/auth/authSocial.ts index 97d9b29f0f..5d37abb9a2 100644 --- a/backend/src/api/auth/authSocial.ts +++ b/backend/src/api/auth/authSocial.ts @@ -2,6 +2,7 @@ import passport from 'passport' import { getServiceChildLogger } from '@crowd/logging' import { API_CONFIG, GITHUB_CONFIG, GOOGLE_CONFIG } from '../../conf' import AuthService from '../../services/auth/authService' +import TenantService from '@/services/tenantService' const log = getServiceChildLogger('AuthSocial') @@ -23,6 +24,11 @@ export default (app, routes) => { req.body.tenantId, req, ) + if (!req.body.tenantId && !req.body.invitationToken) { + await new TenantService(req).create({ + name: 'temporaryName', + }) + } await req.responseHandler.success(req, res, payload) }) diff --git a/backend/src/api/dashboard/dashboardGet.ts b/backend/src/api/dashboard/dashboardGet.ts new file mode 100644 index 0000000000..5ca53b7e94 --- /dev/null +++ b/backend/src/api/dashboard/dashboardGet.ts @@ -0,0 +1,11 @@ +import DashboardService from '@/services/dashboardService' +import Permissions from '../../security/permissions' +import PermissionChecker from '../../services/user/permissionChecker' + +export default async (req, res) => { + new PermissionChecker(req).validateHas(Permissions.values.memberRead) + + const payload = await new DashboardService(req).get(req.query) + + await req.responseHandler.success(req, res, payload) +} diff --git a/backend/src/api/dashboard/index.ts b/backend/src/api/dashboard/index.ts new file mode 100644 index 0000000000..36f118ff13 --- /dev/null +++ b/backend/src/api/dashboard/index.ts @@ -0,0 +1,5 @@ +import { safeWrap } from '../../middlewares/errorMiddleware' + +export default (app) => { + app.get(`/tenant/:tenantId/dashboard`, safeWrap(require('./dashboardGet').default)) +} diff --git a/backend/src/api/index.ts b/backend/src/api/index.ts index 35fd1a0ebd..414f136cb8 100644 --- a/backend/src/api/index.ts +++ b/backend/src/api/index.ts @@ -200,6 +200,7 @@ setImmediate(async () => { require('./systemStatus').default(routes) require('./eventTracking').default(routes) require('./customViews').default(routes) + require('./dashboard').default(routes) require('./premium/enrichment').default(routes) // Loads the Tenant if the :tenantId param is passed routes.param('tenantId', tenantMiddleware) diff --git a/backend/src/api/integration/helpers/redditValidator.ts b/backend/src/api/integration/helpers/redditValidator.ts index 0156e1ebcd..b0f2f1d9b1 100644 --- a/backend/src/api/integration/helpers/redditValidator.ts +++ b/backend/src/api/integration/helpers/redditValidator.ts @@ -1,8 +1,34 @@ import axios from 'axios' import { Error400 } from '@crowd/common' +import { RedisCache, RedisClient } from '@crowd/redis' import Permissions from '../../../security/permissions' import PermissionChecker from '../../../services/user/permissionChecker' import track from '../../../segment/track' +import { REDDIT_CONFIG } from '@/conf' + +const getRedditToken = async (redis: RedisClient, logger: any) => { + const cache = new RedisCache('reddit-global-access-token', redis, logger) + const token = await cache.get('reddit-token') + if (token) { + return token + } + const result = await axios.post( + 'https://www.reddit.com/api/v1/access_token', + 'grant_type=client_credentials', + { + auth: { + username: REDDIT_CONFIG.clientId, + password: REDDIT_CONFIG.clientSecret, + }, + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + }, + ) + // cache for 30 minutes + await cache.set('reddit-token', result.data.access_token, 30 * 60) + return result.data.access_token +} export default async (req, res) => { new PermissionChecker(req).validateHasAny([ @@ -11,14 +37,28 @@ export default async (req, res) => { ]) if (req.query.subreddit) { + let token: string try { - const result = await axios.get( - `https://www.reddit.com/r/${req.query.subreddit}/new.json?limit=1`, + token = await getRedditToken(req.redis, req.log) + } catch (e) { + req.log.error(e) + return req.responseHandler.error(req, res, new Error400(req.language)) + } + try { + const result = await axios.post( + `https://oauth.reddit.com/api/search_reddit_names`, + `query=${req.query.subreddit}&exact=true`, + { + headers: { + ContentType: 'application/x-www-form-urlencoded', + Authorization: `Bearer ${token}`, + }, + }, ) if ( result.status === 200 && - result.data.data.children && - result.data.data.children.length > 0 + result.data.names && + result.data.names.includes(req.query.subreddit) ) { track( 'Reddit: subreddit input', @@ -28,8 +68,18 @@ export default async (req, res) => { }, { ...req }, ) - return req.responseHandler.success(req, res, result.data.data.children) + return req.responseHandler.success(req, res, true) } + // for other status codes we return error + track( + 'Reddit: subreddit input', + { + subreddit: req.query.subreddit, + valid: false, + }, + { ...req }, + ) + return req.responseHandler.error(req, res, new Error400(req.language)) } catch (e) { track( 'Reddit: subreddit input', @@ -39,6 +89,7 @@ export default async (req, res) => { }, { ...req }, ) + req.log.error(e) return req.responseHandler.error(req, res, new Error400(req.language)) } } @@ -50,5 +101,6 @@ export default async (req, res) => { }, { ...req }, ) + req.log.error('Reddit: subreddit input is empty') return req.responseHandler.error(req, res, new Error400(req.language)) } diff --git a/backend/src/api/integration/helpers/youtubeConnect.ts b/backend/src/api/integration/helpers/youtubeConnect.ts new file mode 100644 index 0000000000..c8ec4c89c4 --- /dev/null +++ b/backend/src/api/integration/helpers/youtubeConnect.ts @@ -0,0 +1,9 @@ +import Permissions from '../../../security/permissions' +import IntegrationService from '../../../services/integrationService' +import PermissionChecker from '../../../services/user/permissionChecker' + +export default async (req, res) => { + new PermissionChecker(req).validateHas(Permissions.values.tenantEdit) + const payload = await new IntegrationService(req).connectYoutube(req.body) + await req.responseHandler.success(req, res, payload) +} diff --git a/backend/src/api/integration/index.ts b/backend/src/api/integration/index.ts index 8bd7720c3b..1d7f72f68d 100644 --- a/backend/src/api/integration/index.ts +++ b/backend/src/api/integration/index.ts @@ -263,4 +263,9 @@ export default (app) => { safeWrap(require('./helpers/slackAuthenticateCallback').default), ) } + + app.post( + '/tenant/:tenantId/youtube-connect', + safeWrap(require('./helpers/youtubeConnect').default), + ) } diff --git a/backend/src/api/member/memberFind.ts b/backend/src/api/member/memberFind.ts index e95dfc4cfe..7d6de9b14e 100644 --- a/backend/src/api/member/memberFind.ts +++ b/backend/src/api/member/memberFind.ts @@ -1,8 +1,8 @@ -import { isFeatureEnabled } from '@crowd/feature-flags' import { FeatureFlag } from '@crowd/types' import Permissions from '../../security/permissions' import MemberService from '../../services/memberService' import PermissionChecker from '../../services/user/permissionChecker' +import isFeatureEnabled from '../../feature-flags/isFeatureEnabled' /** * GET /tenant/{tenantId}/member/{id} @@ -34,7 +34,12 @@ export default async (req, res) => { } } - const payload = await new MemberService(req).findById(req.params.id, true, true, segmentId) + let payload + if (await isFeatureEnabled(FeatureFlag.SERVE_PROFILES_OPENSEARCH, req)) { + payload = await new MemberService(req).findByIdOpensearch(req.params.id, segmentId) + } else { + payload = await new MemberService(req).findById(req.params.id, true, true, segmentId) + } await req.responseHandler.success(req, res, payload) } diff --git a/backend/src/api/organization/index.ts b/backend/src/api/organization/index.ts index 9d69c713a9..43a510241b 100644 --- a/backend/src/api/organization/index.ts +++ b/backend/src/api/organization/index.ts @@ -14,6 +14,10 @@ export default (app) => { safeWrap(require('./organizationAutocomplete').default), ) app.get(`/tenant/:tenantId/organization`, safeWrap(require('./organizationList').default)) + app.get( + `/tenant/:tenantId/organization/active`, + safeWrap(require('./organizationActiveList').default), + ) app.get(`/tenant/:tenantId/organization/:id`, safeWrap(require('./organizationFind').default)) app.put( diff --git a/backend/src/api/organization/organizationActiveList.ts b/backend/src/api/organization/organizationActiveList.ts new file mode 100644 index 0000000000..f59af2ed63 --- /dev/null +++ b/backend/src/api/organization/organizationActiveList.ts @@ -0,0 +1,51 @@ +import { Error400 } from '@crowd/common' +import { IActiveOrganizationFilter } from '../../database/repositories/types/organizationTypes' +import Permissions from '../../security/permissions' +import OrganizationService from '../../services/organizationService' +import PermissionChecker from '../../services/user/permissionChecker' + +export default async (req, res) => { + new PermissionChecker(req).validateHas(Permissions.values.memberRead) + + let offset = 0 + if (req.query.offset) { + offset = parseInt(req.query.offset, 10) + } + let limit = 20 + if (req.query.limit) { + limit = parseInt(req.query.limit, 10) + } + + if (req.query.filter?.activityTimestampFrom === undefined) { + throw new Error400(req.language, 'errors.members.activeList.activityTimestampFrom') + } + + if (req.query.filter?.activityTimestampTo === undefined) { + throw new Error400(req.language, 'errors.members.activeList.activityTimestampTo') + } + + const filters: IActiveOrganizationFilter = { + platforms: + req.query.filter?.platforms !== undefined + ? req.query.filter?.platforms.split(',') + : undefined, + isTeamOrganization: + req.query.filter?.isTeamOrganization === undefined + ? undefined + : req.query.filter?.isTeamOrganization === 'true', + activityTimestampFrom: req.query.filter?.activityTimestampFrom, + activityTimestampTo: req.query.filter?.activityTimestampTo, + } + + const orderBy = req.query.orderBy || 'activityCount_DESC' + + const payload = await new OrganizationService(req).findAndCountActive( + filters, + offset, + limit, + orderBy, + req.query.segments, + ) + + await req.responseHandler.success(req, res, payload) +} diff --git a/backend/src/api/organization/organizationFind.ts b/backend/src/api/organization/organizationFind.ts index 79888a0d38..a45ad7df12 100644 --- a/backend/src/api/organization/organizationFind.ts +++ b/backend/src/api/organization/organizationFind.ts @@ -1,8 +1,8 @@ import { FeatureFlag } from '@crowd/types' -import isFeatureEnabled from '@/feature-flags/isFeatureEnabled' import Permissions from '../../security/permissions' import OrganizationService from '../../services/organizationService' import PermissionChecker from '../../services/user/permissionChecker' +import isFeatureEnabled from '../../feature-flags/isFeatureEnabled' /** * GET /tenant/{tenantId}/organization/{id} @@ -34,7 +34,12 @@ export default async (req, res) => { } } - const payload = await new OrganizationService(req).findById(req.params.id, segmentId) + let payload + if (await isFeatureEnabled(FeatureFlag.SERVE_PROFILES_OPENSEARCH, req)) { + payload = await new OrganizationService(req).findByIdOpensearch(req.params.id, segmentId) + } else { + payload = await new OrganizationService(req).findById(req.params.id, segmentId) + } await req.responseHandler.success(req, res, payload) } diff --git a/backend/src/api/organization/organizationMerge.ts b/backend/src/api/organization/organizationMerge.ts index 0ed9e2cc43..6c1f70a2d0 100644 --- a/backend/src/api/organization/organizationMerge.ts +++ b/backend/src/api/organization/organizationMerge.ts @@ -14,7 +14,7 @@ export default async (req, res) => { secondary: secondaryOrgId, } - await new OrganizationService(req).mergeAsync(primaryOrgId, secondaryOrgId) + await new OrganizationService(req).mergeSync(primaryOrgId, secondaryOrgId) track('Merge organizations', requestPayload, { ...req }) diff --git a/backend/src/api/organization/organizationUpdate.ts b/backend/src/api/organization/organizationUpdate.ts index 2bfed8211e..42509dd842 100644 --- a/backend/src/api/organization/organizationUpdate.ts +++ b/backend/src/api/organization/organizationUpdate.ts @@ -21,7 +21,13 @@ import PermissionChecker from '../../services/user/permissionChecker' export default async (req, res) => { new PermissionChecker(req).validateHas(Permissions.values.organizationEdit) - const payload = await new OrganizationService(req).update(req.params.id, req.body, true) + const payload = await new OrganizationService(req).update( + req.params.id, + req.body, + true, + true, + true, + ) await req.responseHandler.success(req, res, payload) } diff --git a/backend/src/api/plan/stripe/checkout.ts b/backend/src/api/plan/stripe/checkout.ts index e109902211..98cedf4a9d 100644 --- a/backend/src/api/plan/stripe/checkout.ts +++ b/backend/src/api/plan/stripe/checkout.ts @@ -1,4 +1,5 @@ import { Error400, Error403 } from '@crowd/common' +import { TenantPlans } from '@crowd/types' import { PLANS_CONFIG } from '../../../conf' import Plans from '../../../security/plans' import TenantService from '../../../services/tenantService' @@ -19,7 +20,7 @@ export default async (req, res) => { } if ( - currentTenant.plan !== Plans.values.essential && + currentTenant.plan !== TenantPlans.Essential && currentTenant.planStatus !== 'cancel_at_period_end' && currentTenant.planUserId !== currentUser.id ) { diff --git a/backend/src/api/plan/stripe/portal.ts b/backend/src/api/plan/stripe/portal.ts index 4506af4951..34ec6fd94f 100644 --- a/backend/src/api/plan/stripe/portal.ts +++ b/backend/src/api/plan/stripe/portal.ts @@ -1,6 +1,6 @@ import { Error400, Error403 } from '@crowd/common' +import { TenantPlans } from '@crowd/types' import { PLANS_CONFIG } from '../../../conf' -import Plans from '../../../security/plans' import TenantService from '../../../services/tenantService' import { tenantSubdomain } from '../../../services/tenantSubdomain' @@ -19,7 +19,7 @@ export default async (req, res) => { } if ( - currentTenant.plan !== Plans.values.essential && + currentTenant.plan !== TenantPlans.Essential && currentTenant.planStatus !== 'cancel_at_period_end' && currentTenant.planUserId !== currentUser.id ) { diff --git a/backend/src/api/premium/enrichment/memberEnrich.ts b/backend/src/api/premium/enrichment/memberEnrich.ts index 73488b9438..abe1bbd663 100644 --- a/backend/src/api/premium/enrichment/memberEnrich.ts +++ b/backend/src/api/premium/enrichment/memberEnrich.ts @@ -1,6 +1,6 @@ import { RedisCache } from '@crowd/redis' import { getServiceLogger } from '@crowd/logging' -import { FeatureFlagRedisKey } from '@crowd/types' +import { FeatureFlagRedisKey, SyncMode } from '@crowd/types' import { getSecondsTillEndOfMonth } from '../../../utils/timing' import Permissions from '../../../security/permissions' import identifyTenant from '../../../segment/identifyTenant' @@ -29,7 +29,10 @@ const log = getServiceLogger() export default async (req, res) => { new PermissionChecker(req).validateHas(Permissions.values.memberEdit) - const payload = await new MemberEnrichmentService(req).enrichOne(req.params.id) + const payload = await new MemberEnrichmentService(req).enrichOne( + req.params.id, + SyncMode.SYNCHRONOUS, + ) track('Single member enrichment', { memberId: req.params.id }, { ...req }) diff --git a/backend/src/api/premium/enrichment/memberEnrichBulk.ts b/backend/src/api/premium/enrichment/memberEnrichBulk.ts index c385fa6204..ae411b6db1 100644 --- a/backend/src/api/premium/enrichment/memberEnrichBulk.ts +++ b/backend/src/api/premium/enrichment/memberEnrichBulk.ts @@ -1,15 +1,14 @@ import { RedisCache } from '@crowd/redis' import { getServiceLogger } from '@crowd/logging' import { Error403 } from '@crowd/common' -import { FeatureFlag, FeatureFlagRedisKey } from '@crowd/types' +import { FeatureFlag, FeatureFlagRedisKey, PLAN_LIMITS } from '@crowd/types' import { getSecondsTillEndOfMonth } from '../../../utils/timing' import Permissions from '../../../security/permissions' import identifyTenant from '../../../segment/identifyTenant' -import { sendBulkEnrichMessage } from '../../../serverless/utils/nodeWorkerSQS' import PermissionChecker from '../../../services/user/permissionChecker' import track from '../../../segment/track' -import { PLAN_LIMITS } from '../../../feature-flags/isFeatureEnabled' import SequelizeRepository from '../../../database/repositories/sequelizeRepository' +import { getNodejsWorkerEmitter } from '@/serverless/utils/serviceSQS' const log = getServiceLogger() @@ -54,7 +53,8 @@ export default async (req, res) => { ) // send the message - await sendBulkEnrichMessage(tenant, membersToEnrich, segmentIds) + const emitter = await getNodejsWorkerEmitter() + await emitter.bulkEnrich(tenant, membersToEnrich, segmentIds) // update enrichment count, we'll also check failed enrichments and deduct these from grand total in bulkEnrichmentWorker const secondsRemainingUntilEndOfMonth = getSecondsTillEndOfMonth() diff --git a/backend/src/api/tenant/index.ts b/backend/src/api/tenant/index.ts index 97096f37d9..84f781c8f1 100644 --- a/backend/src/api/tenant/index.ts +++ b/backend/src/api/tenant/index.ts @@ -28,4 +28,8 @@ export default (app) => { safeWrap(require('./tenantViewOrganizations').default), ) app.post(`/tenant/:tenantId/viewContacts`, safeWrap(require('./tenantViewContacts').default)) + app.post( + `/tenant/:tenantId/payment/confirm`, + safeWrap(require('./tenantPaymentConfirmation').default), + ) } diff --git a/backend/src/api/tenant/tenantPaymentConfirmation.ts b/backend/src/api/tenant/tenantPaymentConfirmation.ts new file mode 100644 index 0000000000..bec0421b24 --- /dev/null +++ b/backend/src/api/tenant/tenantPaymentConfirmation.ts @@ -0,0 +1,25 @@ +import { Error403 } from '@crowd/common' +import telemetryTrack from '../../segment/telemetryTrack' +import track from '../../segment/track' +import TenantService from '../../services/tenantService' + +export default async (req, res) => { + if (!req.currentUser || !req.currentUser.id) { + throw new Error403(req.language) + } + + const payload = await new TenantService(req).confirmPayment(req.params.tenantId, req.body) + + track( + 'Tenant Payment', + { + id: payload.id, + plan: payload.plan, + }, + { ...req }, + ) + + telemetryTrack('Tenant payment', {}, { ...req }) + + await req.responseHandler.success(req, res, payload) +} diff --git a/backend/src/api/tenant/tenantUpdate.ts b/backend/src/api/tenant/tenantUpdate.ts index 78f01ee1de..87eb731b7a 100644 --- a/backend/src/api/tenant/tenantUpdate.ts +++ b/backend/src/api/tenant/tenantUpdate.ts @@ -1,5 +1,6 @@ import { Error403 } from '@crowd/common' import TenantService from '../../services/tenantService' +import identifyTenant from '@/segment/identifyTenant' export default async (req, res) => { if (!req.currentUser || !req.currentUser.id) { @@ -10,5 +11,7 @@ export default async (req, res) => { // checked inside the service const payload = await new TenantService(req).update(req.params.id, req.body) + identifyTenant({ ...req, currentTenant: payload }) + await req.responseHandler.success(req, res, payload) } diff --git a/backend/src/bin/discord-ws.ts b/backend/src/bin/discord-ws.ts index 98cda5c245..ac94e2ebce 100644 --- a/backend/src/bin/discord-ws.ts +++ b/backend/src/bin/discord-ws.ts @@ -140,25 +140,24 @@ async function spawnClient( }) // listen to discord events - client.on(Events.GuildMemberAdd, async (m) => { - const member = m as any + client.on(Events.GuildMemberAdd, async (member) => { + // discord.js is cruel. member object here is typed, + // but it has custom toString and toJSON methods + // and they you print and JSON.stringify it + // the structure turns out to be different await executeIfNotExists( - `member-${member.userId}`, + `discord-ws-member-${member.user.id}-${member.guild.id}`, cache, async () => { logger.debug( { member: member.displayName, - guildId: member.guildId ?? member.guild.id, - userId: member.userId, + guildId: member.guild.id, + userId: member.user.id, }, 'Member joined guild!', ) - await processPayload( - DiscordWebsocketEvent.MEMBER_ADDED, - member, - member.guildId ?? member.guild.id, - ) + await processPayload(DiscordWebsocketEvent.MEMBER_ADDED, member, member.guild.id) }, delayMilliseconds, ) @@ -167,7 +166,7 @@ async function spawnClient( client.on(Events.MessageCreate, async (message) => { if (message.type === MessageType.Default || message.type === MessageType.Reply) { await executeIfNotExists( - `msg-${message.id}`, + `discord-ws-msg-${message.id}`, cache, async () => { logger.debug( diff --git a/backend/src/bin/jobs/checkStuckIntegrationRuns.ts b/backend/src/bin/jobs/checkStuckIntegrationRuns.ts index 3c859c29ec..9b26846fcc 100644 --- a/backend/src/bin/jobs/checkStuckIntegrationRuns.ts +++ b/backend/src/bin/jobs/checkStuckIntegrationRuns.ts @@ -1,20 +1,15 @@ -import { processPaginated } from '@crowd/common' import { Logger, getChildLogger, getServiceChildLogger } from '@crowd/logging' +import { IntegrationRunState } from '@crowd/types' import cronGenerator from 'cron-time-generator' import moment from 'moment' -import { IntegrationRunState } from '@crowd/types' import { INTEGRATION_PROCESSING_CONFIG } from '../../conf' -import IncomingWebhookRepository from '../../database/repositories/incomingWebhookRepository' import IntegrationRepository from '../../database/repositories/integrationRepository' import IntegrationRunRepository from '../../database/repositories/integrationRunRepository' import IntegrationStreamRepository from '../../database/repositories/integrationStreamRepository' import SequelizeRepository from '../../database/repositories/sequelizeRepository' -import { sendNodeWorkerMessage } from '../../serverless/utils/nodeWorkerSQS' import { IntegrationRun } from '../../types/integrationRunTypes' import { IntegrationStreamState } from '../../types/integrationStreamTypes' import { CrowdJob } from '../../types/jobTypes' -import { NodeWorkerProcessWebhookMessage } from '../../types/mq/nodeWorkerProcessWebhookMessage' -import { WebhookProcessor } from '../../serverless/integrations/services/webhookProcessor' const log = getServiceChildLogger('checkStuckIntegrationRuns') @@ -221,32 +216,6 @@ export const checkRuns = async (): Promise => { } } -export const checkStuckWebhooks = async (): Promise => { - const dbOptions = await SequelizeRepository.getDefaultIRepositoryOptions() - const repo = new IncomingWebhookRepository(dbOptions) - - // update retryable error state webhooks to pending state - let errorWebhooks = await repo.findError(1, 20, WebhookProcessor.MAX_RETRY_LIMIT) - - while (errorWebhooks.length > 0) { - await repo.markAllPending(errorWebhooks.map((w) => w.id)) - errorWebhooks = await repo.findError(1, 20, WebhookProcessor.MAX_RETRY_LIMIT) - } - - await processPaginated( - async (page) => repo.findPending(page, 20), - async (webhooks) => { - for (const webhook of webhooks) { - log.warn({ id: webhook.id }, 'Found stuck webhook! Restarting it!') - await sendNodeWorkerMessage( - webhook.tenantId, - new NodeWorkerProcessWebhookMessage(webhook.tenantId, webhook.id), - ) - } - }, - ) -} - const job: CrowdJob = { name: 'Detect & Fix Stuck Integration Runs', cronTime: cronGenerator.every(90).minutes(), @@ -254,7 +223,7 @@ const job: CrowdJob = { if (!running) { running = true try { - await Promise.all([checkRuns(), checkStuckIntegrations(), checkStuckWebhooks()]) + await Promise.all([checkRuns(), checkStuckIntegrations()]) } finally { running = false } diff --git a/backend/src/bin/jobs/downgradeExpiredPlans.ts b/backend/src/bin/jobs/downgradeExpiredPlans.ts deleted file mode 100644 index cf2058175a..0000000000 --- a/backend/src/bin/jobs/downgradeExpiredPlans.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { getServiceChildLogger } from '@crowd/logging' -import cronGenerator from 'cron-time-generator' -import SequelizeRepository from '../../database/repositories/sequelizeRepository' -import Plans from '../../security/plans' -import { CrowdJob } from '../../types/jobTypes' - -const log = getServiceChildLogger('downgradeExpiredPlansCronJob') - -const job: CrowdJob = { - name: 'Downgrade Expired Trial Plans', - // every day - cronTime: cronGenerator.every(1).days(), - onTrigger: async () => { - log.info('Downgrading expired trial plans.') - const dbOptions = await SequelizeRepository.getDefaultIRepositoryOptions() - - const expiredTrialTenants = await dbOptions.database.sequelize.query( - `select t.id, t.name from tenants t - where t."isTrialPlan" and t."trialEndsAt" < now()`, - ) - - for (const tenant of expiredTrialTenants[0]) { - await dbOptions.database.tenant.update( - { isTrialPlan: false, trialEndsAt: null, plan: Plans.values.essential }, - { returning: true, raw: true, where: { id: tenant.id } }, - ) - } - - log.info('Downgrading expired non-trial plans') - const expiredNonTrialTenants = await dbOptions.database.sequelize.query( - `select t.id, t.name from tenants t - where (t.plan = ${Plans.values.growth} or t.plan = ${Plans.values.eagleEye} or t.plan = ${Plans.values.scale}) and t."planSubscriptionEndsAt" is not null and t."planSubscriptionEndsAt" + interval '3 days' < now()`, - ) - - for (const tenant of expiredNonTrialTenants[0]) { - await dbOptions.database.tenant.update( - { plan: Plans.values.essential }, - { returning: true, raw: true, where: { id: tenant.id } }, - ) - } - }, -} - -export default job diff --git a/backend/src/bin/jobs/index.ts b/backend/src/bin/jobs/index.ts index e1a2cb231c..7b4e723adc 100644 --- a/backend/src/bin/jobs/index.ts +++ b/backend/src/bin/jobs/index.ts @@ -3,7 +3,6 @@ import integrationTicks from './integrationTicks' import memberScoreCoordinator from './memberScoreCoordinator' import refreshMaterializedViews from './refreshMaterializedViews' import refreshMaterializedViewsForCube from './refreshMaterializedViewsForCube' -import downgradeExpiredPlans from './downgradeExpiredPlans' import integrationDataChecker from './integrationDataChecker' import mergeSuggestions from './mergeSuggestions' import refreshSampleData from './refreshSampleData' @@ -16,7 +15,6 @@ const jobs: CrowdJob[] = [ memberScoreCoordinator, refreshMaterializedViews, refreshMaterializedViewsForCube, - downgradeExpiredPlans, integrationDataChecker, mergeSuggestions, refreshSampleData, diff --git a/backend/src/bin/jobs/integrationDataChecker.ts b/backend/src/bin/jobs/integrationDataChecker.ts index 8568b2e1fe..32a1600db9 100644 --- a/backend/src/bin/jobs/integrationDataChecker.ts +++ b/backend/src/bin/jobs/integrationDataChecker.ts @@ -1,8 +1,6 @@ +import { getNodejsWorkerEmitter } from '@/serverless/utils/serviceSQS' import SequelizeRepository from '../../database/repositories/sequelizeRepository' import { CrowdJob } from '../../types/jobTypes' -import { sendNodeWorkerMessage } from '../../serverless/utils/nodeWorkerSQS' -import { NodeWorkerMessageType } from '../../serverless/types/workerTypes' -import { NodeWorkerMessageBase } from '../../types/mq/nodeWorkerMessageBase' const job: CrowdJob = { name: 'Integration Data Checker', @@ -17,13 +15,9 @@ const job: CrowdJob = { }, }) + const emitter = await getNodejsWorkerEmitter() for (const integration of integrations) { - await sendNodeWorkerMessage(integration.id, { - tenantId: integration.tenantId, - type: NodeWorkerMessageType.NODE_MICROSERVICE, - integrationId: integration.id, - service: 'integration-data-checker', - } as NodeWorkerMessageBase) + await emitter.integrationDataChecker(integration.tenantId, integration.id) } }, } diff --git a/backend/src/bin/jobs/mergeSuggestions.ts b/backend/src/bin/jobs/mergeSuggestions.ts index 8cbc69b1cf..b50e6b9f69 100644 --- a/backend/src/bin/jobs/mergeSuggestions.ts +++ b/backend/src/bin/jobs/mergeSuggestions.ts @@ -1,23 +1,20 @@ +import { timeout, IS_DEV_ENV, IS_TEST_ENV } from '@crowd/common' import cronGenerator from 'cron-time-generator' -import { timeout } from '@crowd/common' +import { getNodejsWorkerEmitter } from '@/serverless/utils/serviceSQS' import TenantService from '../../services/tenantService' import { CrowdJob } from '../../types/jobTypes' -import { sendNodeWorkerMessage } from '../../serverless/utils/nodeWorkerSQS' -import { NodeWorkerMessageType } from '../../serverless/types/workerTypes' -import { NodeWorkerMessageBase } from '../../types/mq/nodeWorkerMessageBase' const job: CrowdJob = { name: 'Merge suggestions', // every 12 hours - cronTime: cronGenerator.every(12).hours(), + cronTime: + IS_DEV_ENV || IS_TEST_ENV ? cronGenerator.every(2).minutes() : cronGenerator.every(12).hours(), onTrigger: async () => { const tenants = await TenantService._findAndCountAllForEveryUser({}) + const emitter = await getNodejsWorkerEmitter() + for (const tenant of tenants.rows) { - await sendNodeWorkerMessage(tenant.id, { - type: NodeWorkerMessageType.NODE_MICROSERVICE, - tenant: tenant.id, - service: 'merge-suggestions', - } as NodeWorkerMessageBase) + await emitter.mergeSuggestions(tenant.id) await timeout(300) } diff --git a/backend/src/bin/jobs/organizationEnricher.ts b/backend/src/bin/jobs/organizationEnricher.ts index 4d0eb48ffa..a9a4b8b357 100644 --- a/backend/src/bin/jobs/organizationEnricher.ts +++ b/backend/src/bin/jobs/organizationEnricher.ts @@ -1,11 +1,9 @@ -import cronGenerator from 'cron-time-generator' import { getServiceLogger } from '@crowd/logging' +import cronGenerator from 'cron-time-generator' +import { getNodejsWorkerEmitter } from '@/serverless/utils/serviceSQS' import SequelizeRepository from '../../database/repositories/sequelizeRepository' -import { CrowdJob } from '../../types/jobTypes' -import { sendNodeWorkerMessage } from '../../serverless/utils/nodeWorkerSQS' -import { NodeWorkerMessageBase } from '../../types/mq/nodeWorkerMessageBase' -import { NodeWorkerMessageType } from '../../serverless/types/workerTypes' import TenantRepository from '../../database/repositories/tenantRepository' +import { CrowdJob } from '../../types/jobTypes' const job: CrowdJob = { name: 'organization enricher', @@ -18,14 +16,10 @@ async function sendWorkerMessage() { const log = getServiceLogger() const tenants = await TenantRepository.getPayingTenantIds(options) log.info(tenants) + + const emitter = await getNodejsWorkerEmitter() for (const { id } of tenants) { - const payload = { - type: NodeWorkerMessageType.NODE_MICROSERVICE, - service: 'enrich-organizations', - tenantId: id, - } as NodeWorkerMessageBase - log.info({ payload }, 'enricher worker payload') - await sendNodeWorkerMessage(id, payload) + await emitter.enrichOrganizations(id) } } diff --git a/backend/src/bin/jobs/refreshMaterializedViews.ts b/backend/src/bin/jobs/refreshMaterializedViews.ts index b924bb889c..3ec36deb28 100644 --- a/backend/src/bin/jobs/refreshMaterializedViews.ts +++ b/backend/src/bin/jobs/refreshMaterializedViews.ts @@ -1,26 +1,71 @@ import cronGenerator from 'cron-time-generator' -import SequelizeRepository from '../../database/repositories/sequelizeRepository' +import { QueryTypes } from 'sequelize' +import { Logger, getChildLogger, getServiceChildLogger, logExecutionTimeV2 } from '@crowd/logging' +import { IS_DEV_ENV, IS_TEST_ENV } from '@crowd/common' import { CrowdJob } from '../../types/jobTypes' +import { databaseInit } from '@/database/databaseConnection' -let processingRefreshMemberAggregteMVs = false +export const refreshMaterializedView = async ( + view: string, + database: any, + log: Logger, +): Promise => { + log = getChildLogger('execution', log, { + view, + }) + try { + const refreshQuery = `refresh materialized view concurrently "${view}"` + const runningQuery = await database.sequelize.query( + ` + select 1 + from pg_stat_activity + where query = :refreshQuery + and state != 'idle' + and pid != pg_backend_pid() + `, + { + replacements: { + refreshQuery, + }, + type: QueryTypes.SELECT, + useMaster: true, + }, + ) -const job: CrowdJob = { - name: 'Refresh Materialized View', - // every two hours - cronTime: cronGenerator.every(2).hours(), - onTrigger: async () => { - if (!processingRefreshMemberAggregteMVs) { - processingRefreshMemberAggregteMVs = true - } else { - return + if (runningQuery.length > 0) { + log.warn( + `Materialized view will not be refreshed because there's already an ongoing refresh for it!`, + ) + return false } - const dbOptions = await SequelizeRepository.getDefaultIRepositoryOptions() - await dbOptions.database.sequelize.query( - 'refresh materialized view concurrently "memberActivityAggregatesMVs"', + log.info('Refreshing materialized view') + await logExecutionTimeV2( + () => + database.sequelize.query(refreshQuery, { + useMaster: true, + }), + log, + `Refresh Materialized View ${view}`, ) - processingRefreshMemberAggregteMVs = false + return true + } catch (err) { + log.error({ error: err }, 'Error while refreshing materialized view!') + return false + } +} + +const job: CrowdJob = { + name: 'Refresh Materialized View', + cronTime: + IS_DEV_ENV || IS_TEST_ENV ? cronGenerator.every(1).minutes() : cronGenerator.every(2).hours(), + onTrigger: async () => { + const database = await databaseInit(1000 * 60 * 15, true) + const log = getServiceChildLogger('RefreshMVJob') + + await refreshMaterializedView('memberActivityAggregatesMVs', database, log) + await refreshMaterializedView('member_segments_mv', database, log) }, } diff --git a/backend/src/bin/jobs/refreshMaterializedViewsForCube.ts b/backend/src/bin/jobs/refreshMaterializedViewsForCube.ts index b09f119522..57024ce233 100644 --- a/backend/src/bin/jobs/refreshMaterializedViewsForCube.ts +++ b/backend/src/bin/jobs/refreshMaterializedViewsForCube.ts @@ -1,20 +1,22 @@ -import { Logger, logExecutionTimeV2 } from '@crowd/logging' -import { QueryTypes } from 'sequelize' +import { Edition } from '@crowd/types' +import { EDITION, IS_DEV_ENV, IS_TEST_ENV } from '@crowd/common' +import { Logger, getServiceChildLogger } from '@crowd/logging' +import { getTemporalClient } from '@crowd/temporal' import { CrowdJob } from '../../types/jobTypes' import { databaseInit } from '../../database/databaseConnection' - -function createRefreshQuery(view: string) { - return `REFRESH MATERIALIZED VIEW CONCURRENTLY "${view}"` -} +import { TEMPORAL_CONFIG } from '@/conf' +import { refreshMaterializedView } from './refreshMaterializedViews' const job: CrowdJob = { name: 'Refresh Materialized View For Cube', - cronTime: '1,31 * * * *', + cronTime: IS_DEV_ENV || IS_TEST_ENV ? '* * * * *' : '1,31 * * * *', onTrigger: async (log: Logger) => { + const refreshed = [] + try { // initialize database with 15 minutes query timeout - const forceNewDbInstance = true - const database = await databaseInit(1000 * 60 * 15, forceNewDbInstance) + const database = await databaseInit(1000 * 60 * 15, true) + const log = getServiceChildLogger('RefreshMVForCubeJob') const materializedViews = [ 'mv_members_cube', @@ -24,45 +26,31 @@ const job: CrowdJob = { ] for (const view of materializedViews) { - const refreshQuery = createRefreshQuery(view) - const runningQuery = await database.sequelize.query( - ` - SELECT 1 - FROM pg_stat_activity - WHERE query = :refreshQuery - AND state != 'idle' - AND pid != pg_backend_pid() - `, - { - replacements: { - refreshQuery, - }, - type: QueryTypes.SELECT, - useMaster: true, - }, - ) - - if (runningQuery.length > 0) { - log.warn( - `Materialized views for cube will not be refreshed because there's already an ongoing refresh of ${view}!`, - ) - return + const result = await refreshMaterializedView(view, database, log) + if (result) { + refreshed.push(view) } } - for (const view of materializedViews) { - const refreshQuery = createRefreshQuery(view) - await logExecutionTimeV2( - () => - database.sequelize.query(refreshQuery, { - useMaster: true, - }), - log, - `Refresh Materialized View ${view}`, - ) - } } catch (e) { log.error({ error: e }, `Error while refreshing materialized views!`) } + + // For LFX we use temporal schedules to trigger this + // it'll only be triggered once a day + if (EDITION !== Edition.LFX && refreshed.length > 0) { + log.info(`Refreshed [${refreshed.join(', ')}] materialized views! Triggering cube refresh!`) + const temporal = await getTemporalClient(TEMPORAL_CONFIG) + + await temporal.workflow.start('spawnDashboardCacheRefreshForAllTenants', { + taskQueue: 'cache', + workflowId: `refreshAllTenants`, + retry: { + maximumAttempts: 10, + }, + args: [], + searchAttributes: {}, + }) + } }, } diff --git a/backend/src/bin/jobs/refreshSampleData.ts b/backend/src/bin/jobs/refreshSampleData.ts index efed37c975..62e16bad3e 100644 --- a/backend/src/bin/jobs/refreshSampleData.ts +++ b/backend/src/bin/jobs/refreshSampleData.ts @@ -1,17 +1,13 @@ +import { getNodejsWorkerEmitter } from '@/serverless/utils/serviceSQS' import { CrowdJob } from '../../types/jobTypes' -import { sendNodeWorkerMessage } from '../../serverless/utils/nodeWorkerSQS' -import { NodeWorkerMessageType } from '../../serverless/types/workerTypes' -import { NodeWorkerMessageBase } from '../../types/mq/nodeWorkerMessageBase' const job: CrowdJob = { name: 'Refresh sample data', // every day cronTime: '0 0 * * *', onTrigger: async () => { - await sendNodeWorkerMessage('refresh-sample-data', { - type: NodeWorkerMessageType.NODE_MICROSERVICE, - service: 'refresh-sample-data', - } as NodeWorkerMessageBase) + const emitter = await getNodejsWorkerEmitter() + await emitter.refreshSampleData() }, } diff --git a/backend/src/bin/nodejs-worker.ts b/backend/src/bin/nodejs-worker.ts index ce29a53699..11b90aa6ec 100644 --- a/backend/src/bin/nodejs-worker.ts +++ b/backend/src/bin/nodejs-worker.ts @@ -1,33 +1,27 @@ import { timeout } from '@crowd/common' import { Logger, getChildLogger, getServiceLogger } from '@crowd/logging' +import { RedisClient, getRedisClient } from '@crowd/redis' import { SqsDeleteMessageRequest, SqsMessage, SqsReceiveMessageRequest, deleteMessage, receiveMessage, - sendMessage, } from '@crowd/sqs' -import { SpanStatusCode, getServiceTracer } from '@crowd/tracing' -import moment from 'moment' -import { getRedisClient, RedisClient } from '@crowd/redis' -import { Sequelize, QueryTypes } from 'sequelize' import fs from 'fs' import path from 'path' +import { QueryTypes, Sequelize } from 'sequelize' import telemetry from '@crowd/telemetry' +import { SQS_CLIENT, getNodejsWorkerEmitter } from '@/serverless/utils/serviceSQS' +import { databaseInit } from '@/database/databaseConnection' import { REDIS_CONFIG, SQS_CONFIG } from '../conf' import { processDbOperationsMessage } from '../serverless/dbOperations/workDispatcher' import { processNodeMicroserviceMessage } from '../serverless/microservices/nodejs/workDispatcher' import { NodeWorkerMessageType } from '../serverless/types/workerTypes' -import { sendNodeWorkerMessage } from '../serverless/utils/nodeWorkerSQS' import { NodeWorkerMessageBase } from '../types/mq/nodeWorkerMessageBase' -import { processIntegration, processWebhook } from './worker/integrations' -import { SQS_CLIENT } from '@/serverless/utils/serviceSQS' -import { databaseInit } from '@/database/databaseConnection' /* eslint-disable no-constant-condition */ -const tracer = getServiceTracer() const serviceLogger = getServiceLogger() let exiting = false @@ -39,12 +33,9 @@ process.on('SIGTERM', async () => { exiting = true }) -const receive = async (delayed?: boolean): Promise => { +const receive = async (queue: string): Promise => { const params: SqsReceiveMessageRequest = { - QueueUrl: delayed ? SQS_CONFIG.nodejsWorkerDelayableQueue : SQS_CONFIG.nodejsWorkerQueue, - MessageAttributeNames: !delayed - ? undefined - : ['remainingDelaySeconds', 'tenantId', 'targetQueueUrl'], + QueueUrl: queue, } const messages = await receiveMessage(SQS_CLIENT(), params) @@ -56,95 +47,18 @@ const receive = async (delayed?: boolean): Promise => { return undefined } -const removeFromQueue = (receiptHandle: string, delayed?: boolean): Promise => { +const removeFromQueue = (queue: string, receiptHandle: string): Promise => { const params: SqsDeleteMessageRequest = { - QueueUrl: delayed ? SQS_CONFIG.nodejsWorkerDelayableQueue : SQS_CONFIG.nodejsWorkerQueue, + QueueUrl: queue, ReceiptHandle: receiptHandle, } return deleteMessage(SQS_CLIENT(), params) } -async function handleDelayedMessages() { - const delayedHandlerLogger = getChildLogger('delayedMessages', serviceLogger, { - queue: SQS_CONFIG.nodejsWorkerDelayableQueue, - }) - delayedHandlerLogger.info('Listing for delayed messages!') - - // noinspection InfiniteLoopJS - while (!exiting) { - const message = await receive(true) - - if (message) { - await tracer.startActiveSpan('ProcessDelayedMessage', async (span) => { - try { - const msg: NodeWorkerMessageBase = JSON.parse(message.Body) - const messageLogger = getChildLogger('messageHandler', serviceLogger, { - messageId: message.MessageId, - type: msg.type, - }) - - if (message.MessageAttributes && message.MessageAttributes.remainingDelaySeconds) { - // re-delay - const newDelay = parseInt( - message.MessageAttributes.remainingDelaySeconds.StringValue, - 10, - ) - const tenantId = message.MessageAttributes.tenantId.StringValue - messageLogger.debug({ newDelay, tenantId }, 'Re-delaying message!') - await sendNodeWorkerMessage(tenantId, msg, newDelay) - } else { - // just emit to the normal queue for processing - const tenantId = message.MessageAttributes.tenantId.StringValue - - if (message.MessageAttributes.targetQueueUrl) { - const targetQueueUrl = message.MessageAttributes.targetQueueUrl.StringValue - messageLogger.debug({ tenantId, targetQueueUrl }, 'Successfully delayed a message!') - await sendMessage(SQS_CLIENT(), { - QueueUrl: targetQueueUrl, - MessageGroupId: tenantId, - MessageDeduplicationId: `${tenantId}-${moment().valueOf()}`, - MessageBody: JSON.stringify(msg), - }) - } else { - messageLogger.debug({ tenantId }, 'Successfully delayed a message!') - await sendNodeWorkerMessage(tenantId, msg) - } - } - - await removeFromQueue(message.ReceiptHandle, true) - span.setStatus({ - code: SpanStatusCode.OK, - }) - } catch (err) { - span.setStatus({ - code: SpanStatusCode.ERROR, - message: err, - }) - } finally { - span.end() - } - }) - } else { - delayedHandlerLogger.trace('No message received!') - } - } - - delayedHandlerLogger.warn('Exiting!') -} - -let processingMessages = 0 -const isWorkerAvailable = (): boolean => processingMessages <= 3 -const addWorkerJob = (): void => { - processingMessages++ -} -const removeWorkerJob = (): void => { - processingMessages-- -} - -async function handleMessages() { +async function handleMessages(queue: string) { const handlerLogger = getChildLogger('messages', serviceLogger, { - queue: SQS_CONFIG.nodejsWorkerQueue, + queue, }) handlerLogger.info('Listening for messages!') @@ -164,30 +78,21 @@ async function handleMessages() { messageLogger.warn( 'Skipping enrich_member_organizations message! Purging the queue because they are not needed anymore!', ) - await removeFromQueue(message.ReceiptHandle) + await removeFromQueue(queue, message.ReceiptHandle) return } - messageLogger.debug( - { messageType: msg.type, messagePayload: JSON.stringify(msg) }, - 'Received a new queue message!', - ) + messageLogger.debug({ messageType: msg.type }, 'Received a new queue message!') let processFunction: (msg: NodeWorkerMessageBase, logger?: Logger) => Promise switch (msg.type) { - case NodeWorkerMessageType.INTEGRATION_PROCESS: - processFunction = processIntegration - break case NodeWorkerMessageType.NODE_MICROSERVICE: processFunction = processNodeMicroserviceMessage break case NodeWorkerMessageType.DB_OPERATIONS: processFunction = processDbOperationsMessage break - case NodeWorkerMessageType.PROCESS_WEBHOOK: - processFunction = processWebhook - break default: messageLogger.error('Error while parsing queue message! Invalid type.') @@ -198,7 +103,7 @@ async function handleMessages() { 'nodejs_worker.process_message', async () => { // remove the message from the queue as it's about to be processed - await removeFromQueue(message.ReceiptHandle) + await removeFromQueue(queue, message.ReceiptHandle) messagesInProgress.set(message.MessageId, msg) try { await processFunction(msg, messageLogger) @@ -212,16 +117,30 @@ async function handleMessages() { type: msg.type, }, ) + } else { + messageLogger.error( + { messageType: msg.type }, + 'Error while parsing queue message! Invalid type.', + ) } } catch (err) { messageLogger.error(err, { payload: msg }, 'Error while processing queue message!') } } + let processingMessages = 0 + const isWorkerAvailable = (): boolean => processingMessages <= 3 + const addWorkerJob = (): void => { + processingMessages++ + } + const removeWorkerJob = (): void => { + processingMessages-- + } + // noinspection InfiniteLoopJS while (!exiting) { if (isWorkerAvailable()) { - const message = await receive() + const message = await receive(queue) if (message) { addWorkerJob() @@ -262,8 +181,12 @@ const initRedisSeq = async () => { setImmediate(async () => { await initRedisSeq() - const promises = [handleMessages(), handleDelayedMessages()] - await Promise.all(promises) + + await getNodejsWorkerEmitter() + await Promise.all([ + handleMessages(SQS_CONFIG.nodejsWorkerQueue), + handleMessages(SQS_CONFIG.nodejsWorkerPriorityQueue), + ]) }) const liveFilePath = path.join(__dirname, 'tmp/nodejs-worker-live.tmp') diff --git a/backend/src/bin/scripts/cache-dashboard.ts b/backend/src/bin/scripts/cache-dashboard.ts new file mode 100644 index 0000000000..cd8df964a4 --- /dev/null +++ b/backend/src/bin/scripts/cache-dashboard.ts @@ -0,0 +1,72 @@ +import commandLineArgs from 'command-line-args' +import commandLineUsage from 'command-line-usage' +import * as fs from 'fs' +import path from 'path' +import { randomUUID } from 'crypto' + +import { getTemporalClient } from '@crowd/temporal' +import { TEMPORAL_CONFIG } from '@/conf' + +/* eslint-disable no-console */ + +const banner = fs.readFileSync(path.join(__dirname, 'banner.txt'), 'utf8') + +const options = [ + { + name: 'help', + alias: 'h', + type: Boolean, + description: 'Print this usage guide.', + }, + { + name: 'tenantId', + alias: 't', + type: String, + description: 'Tenant ID', + }, + { + name: 'allTenants', + alias: 'a', + type: Boolean, + description: 'all tenants', + }, +] +const sections = [ + { + content: banner, + raw: true, + }, + { + header: `Cache dashboard to redis for given tenants`, + content: 'Cache dashboard to redis for given tenants', + }, + { + header: 'Options', + optionList: options, + }, +] + +const usage = commandLineUsage(sections) +const parameters = commandLineArgs(options) + +if (parameters.help) { + console.log(usage) +} else { + setImmediate(async () => { + const temporal = await getTemporalClient(TEMPORAL_CONFIG) + + const uuid = randomUUID() + + await temporal.workflow.start('spawnDashboardCacheRefreshForAllTenants', { + taskQueue: 'cache', + workflowId: `spawnDashboardCacheRefreshForAllTenants/${uuid}`, + retry: { + maximumAttempts: 10, + }, + args: [], + searchAttributes: {}, + }) + + process.exit(0) + }) +} diff --git a/backend/src/bin/scripts/continue-run.ts b/backend/src/bin/scripts/continue-run.ts deleted file mode 100644 index af5dd5be49..0000000000 --- a/backend/src/bin/scripts/continue-run.ts +++ /dev/null @@ -1,103 +0,0 @@ -import commandLineArgs from 'command-line-args' -import commandLineUsage from 'command-line-usage' -import * as fs from 'fs' -import path from 'path' -import { getServiceLogger } from '@crowd/logging' -import { IntegrationRunState } from '@crowd/types' -import SequelizeRepository from '../../database/repositories/sequelizeRepository' -import { sendNodeWorkerMessage } from '../../serverless/utils/nodeWorkerSQS' -import { NodeWorkerIntegrationProcessMessage } from '../../types/mq/nodeWorkerIntegrationProcessMessage' -import IntegrationRunRepository from '../../database/repositories/integrationRunRepository' - -/* eslint-disable no-console */ - -const banner = fs.readFileSync(path.join(__dirname, 'banner.txt'), 'utf8') - -const log = getServiceLogger() - -const options = [ - { - name: 'run', - alias: 'r', - typeLabel: '{underline runId}', - type: String, - description: - 'The unique ID of integration run that you would like to continue processing. Use comma delimiter when sending multiple integration runs.', - }, - { - name: 'disableFiringCrowdWebhooks', - alias: 'd', - typeLabel: '{underline disableFiringCrowdWebhooks}', - type: Boolean, - defaultOption: false, - description: 'Should it disable firing outgoing crowd webhooks?', - }, - { - name: 'help', - alias: 'h', - type: Boolean, - description: 'Print this usage guide.', - }, -] -const sections = [ - { - content: banner, - raw: true, - }, - { - header: 'Continue Processing Integration Run', - content: 'Trigger processing of integration run.', - }, - { - header: 'Options', - optionList: options, - }, -] - -const usage = commandLineUsage(sections) -const parameters = commandLineArgs(options) - -if (parameters.help && !parameters.run) { - console.log(usage) -} else { - setImmediate(async () => { - const options = await SequelizeRepository.getDefaultIRepositoryOptions() - - const fireCrowdWebhooks = !parameters.disableFiringCrowdWebhooks - - const runRepo = new IntegrationRunRepository(options) - - const runIds = parameters.run.split(',') - for (const runId of runIds) { - const run = await runRepo.findById(runId) - - if (!run) { - log.error({ runId }, 'Integration run not found!') - process.exit(1) - } else { - await log.info({ runId }, 'Integration run found - triggering SQS message!') - - if (run.state !== IntegrationRunState.PENDING) { - log.warn( - { currentState: run.state }, - `Setting integration state to ${IntegrationRunState.PENDING}!`, - ) - await runRepo.restart(run.id) - } - - if (!fireCrowdWebhooks) { - log.info( - 'fireCrowdWebhooks is false - This continue-run will not trigger outgoing crowd webhooks!', - ) - } - - await sendNodeWorkerMessage( - run.tenantId, - new NodeWorkerIntegrationProcessMessage(run.id, null, fireCrowdWebhooks), - ) - } - } - - process.exit(0) - }) -} diff --git a/backend/src/bin/scripts/enrich-members-and-organizations.ts b/backend/src/bin/scripts/enrich-members-and-organizations.ts index 0943cc3045..ea89bbf40e 100644 --- a/backend/src/bin/scripts/enrich-members-and-organizations.ts +++ b/backend/src/bin/scripts/enrich-members-and-organizations.ts @@ -1,16 +1,14 @@ +import { getServiceLogger } from '@crowd/logging' import commandLineArgs from 'command-line-args' import commandLineUsage from 'command-line-usage' import * as fs from 'fs' import path from 'path' -import { getServiceLogger } from '@crowd/logging' -import SequelizeRepository from '@/database/repositories/sequelizeRepository' +import { IRepositoryOptions } from '@/database/repositories/IRepositoryOptions' import MemberRepository from '@/database/repositories/memberRepository' -import { sendBulkEnrichMessage, sendNodeWorkerMessage } from '@/serverless/utils/nodeWorkerSQS' import OrganizationRepository from '@/database/repositories/organizationRepository' -import { NodeWorkerMessageType } from '@/serverless/types/workerTypes' -import { NodeWorkerMessageBase } from '@/types/mq/nodeWorkerMessageBase' +import SequelizeRepository from '@/database/repositories/sequelizeRepository' import getUserContext from '@/database/utils/getUserContext' -import { IRepositoryOptions } from '@/database/repositories/IRepositoryOptions' +import { getNodejsWorkerEmitter } from '@/serverless/utils/serviceSQS' import SegmentService from '@/services/segmentService' /* eslint-disable no-console */ @@ -80,6 +78,7 @@ if (parameters.help || (!parameters.tenant && (!parameters.organization || !para const enrichMembers = parameters.member const enrichOrganizations = parameters.organization const limit = 1000 + const emitter = await getNodejsWorkerEmitter() for (const tenantId of tenantIds) { const options = await SequelizeRepository.getDefaultIRepositoryOptions() @@ -112,7 +111,7 @@ if (parameters.help || (!parameters.tenant && (!parameters.organization || !para if (enrichMembers) { if (parameters.memberIds) { const memberIds = parameters.memberIds.split(',') - await sendBulkEnrichMessage(tenantId, memberIds, segmentIds, false, true) + await emitter.bulkEnrich(tenantId, memberIds, segmentIds, false, true) log.info( { tenantId }, `Enrichment message for ${memberIds.length} sent to nodejs-worker!`, @@ -134,7 +133,7 @@ if (parameters.help || (!parameters.tenant && (!parameters.organization || !para optionsWithTenant, ) - await sendBulkEnrichMessage(tenantId, memberIds, segmentIds, false, true) + await emitter.bulkEnrich(tenantId, memberIds, segmentIds, false, true) offset += limit } while (totalMembers > offset) @@ -150,16 +149,7 @@ if (parameters.help || (!parameters.tenant && (!parameters.organization || !para log.info({ tenantId }, `Total organizations found in the tenant: ${totalOrganizations}`) - const payload = { - type: NodeWorkerMessageType.NODE_MICROSERVICE, - service: 'enrich-organizations', - tenantId, - // Since there is no pagination implemented for the organizations enrichment, - // we set a limit of 10,000 to ensure all organizations are included when enriched in bulk. - maxEnrichLimit: 10000, - } as NodeWorkerMessageBase - - await sendNodeWorkerMessage(tenantId, payload) + await emitter.enrichOrganizations(tenantId, 10000) log.info( { tenantId }, `Organizations enrichment operation finished for tenant ${tenantId}`, diff --git a/backend/src/bin/scripts/generate-merge-suggestions-synchronous.ts b/backend/src/bin/scripts/generate-merge-suggestions-synchronous.ts new file mode 100644 index 0000000000..3b5d4e614f --- /dev/null +++ b/backend/src/bin/scripts/generate-merge-suggestions-synchronous.ts @@ -0,0 +1,102 @@ +import commandLineArgs from 'command-line-args' +import commandLineUsage from 'command-line-usage' +import { getOpensearchClient } from '@crowd/opensearch' +import { OrganizationMergeSuggestionType } from '@crowd/types' +import * as fs from 'fs' +import path from 'path' +import { IRepositoryOptions } from '@/database/repositories/IRepositoryOptions' +import getUserContext from '@/database/utils/getUserContext' +import SegmentService from '@/services/segmentService' +import { OPENSEARCH_CONFIG } from '@/conf' +import OrganizationService from '@/services/organizationService' +import TenantService from '@/services/tenantService' + +/* eslint-disable no-console */ + +const banner = fs.readFileSync(path.join(__dirname, 'banner.txt'), 'utf8') + +const options = [ + { + name: 'tenant', + alias: 't', + type: String, + description: + 'The unique ID of that tenant that you would like to generate merge suggestions for.', + }, + { + name: 'plan', + alias: 'p', + type: String, + description: + 'Comma separated plans - works with allTenants flag. Only generate suggestions for tenants with specific plans. Available plans: Growth, Scale, Enterprise', + }, + { + name: 'allTenants', + alias: 'a', + type: Boolean, + defaultValue: false, + description: 'Set this flag to merge similar organizations for all tenants.', + }, + { + name: 'help', + alias: 'h', + type: Boolean, + description: 'Print this usage guide.', + }, +] +const sections = [ + { + content: banner, + raw: true, + }, + { + header: 'Generate merge suggestions for a tenant', + content: 'Generate merge suggestions for a tenant', + }, + { + header: 'Options', + optionList: options, + }, +] + +const usage = commandLineUsage(sections) +const parameters = commandLineArgs(options) + +if (parameters.help || (!parameters.tenant && !parameters.allTenants)) { + console.log(usage) +} else { + setImmediate(async () => { + let tenantIds + + if (parameters.allTenants) { + tenantIds = (await TenantService._findAndCountAllForEveryUser({})).rows + if (parameters.plan) { + tenantIds = tenantIds.filter((tenant) => parameters.plan.split(',').includes(tenant.plan)) + } + tenantIds = tenantIds.map((t) => t.id) + } else if (parameters.tenant) { + tenantIds = parameters.tenant.split(',') + } else { + tenantIds = [] + } + + for (const tenantId of tenantIds) { + const userContext: IRepositoryOptions = await getUserContext(tenantId) + const segmentService = new SegmentService(userContext) + const { rows: segments } = await segmentService.querySubprojects({}) + userContext.currentSegments = segments + userContext.opensearch = getOpensearchClient(OPENSEARCH_CONFIG) + + console.log(`Generating organization merge suggestions for tenant ${tenantId}!`) + + const organizationService = new OrganizationService(userContext) + await organizationService.generateMergeSuggestions( + OrganizationMergeSuggestionType.BY_IDENTITY, + ) + + console.log(`Done generating organization merge suggestions for tenant ${tenantId}!`) + } + + process.exit(0) + }) +} diff --git a/backend/src/bin/scripts/generate-merge-suggestions.ts b/backend/src/bin/scripts/generate-merge-suggestions.ts index 911f5fc184..4d96f1a3e1 100644 --- a/backend/src/bin/scripts/generate-merge-suggestions.ts +++ b/backend/src/bin/scripts/generate-merge-suggestions.ts @@ -2,9 +2,7 @@ import commandLineArgs from 'command-line-args' import commandLineUsage from 'command-line-usage' import * as fs from 'fs' import path from 'path' -import { sendNodeWorkerMessage } from '../../serverless/utils/nodeWorkerSQS' -import { NodeWorkerMessageType } from '../../serverless/types/workerTypes' -import { NodeWorkerMessageBase } from '@/types/mq/nodeWorkerMessageBase' +import { getNodejsWorkerEmitter } from '@/serverless/utils/serviceSQS' /* eslint-disable no-console */ @@ -48,13 +46,9 @@ if (parameters.help || !parameters.tenant) { } else { setImmediate(async () => { const tenantIds = parameters.tenant.split(',') - + const emitter = await getNodejsWorkerEmitter() for (const tenantId of tenantIds) { - await sendNodeWorkerMessage(tenantId, { - type: NodeWorkerMessageType.NODE_MICROSERVICE, - tenant: tenantId, - service: 'merge-suggestions', - } as NodeWorkerMessageBase) + await emitter.mergeSuggestions(tenantId) } process.exit(0) diff --git a/backend/src/bin/scripts/merge-similar-organizations.ts b/backend/src/bin/scripts/merge-similar-organizations.ts new file mode 100644 index 0000000000..5199f4c4ab --- /dev/null +++ b/backend/src/bin/scripts/merge-similar-organizations.ts @@ -0,0 +1,177 @@ +import commandLineArgs from 'command-line-args' +import commandLineUsage from 'command-line-usage' +import { QueryTypes } from 'sequelize' +import * as fs from 'fs' +import path from 'path' +import SequelizeRepository from '../../database/repositories/sequelizeRepository' +import TenantService from '@/services/tenantService' +import OrganizationService from '@/services/organizationService' +import getUserContext from '@/database/utils/getUserContext' +import { IRepositoryOptions } from '@/database/repositories/IRepositoryOptions' +import { + MergeActionState, + MergeActionType, + MergeActionsRepository, +} from '@/database/repositories/mergeActionsRepository' + +/* eslint-disable no-console */ + +const banner = fs.readFileSync(path.join(__dirname, 'banner.txt'), 'utf8') + +const options = [ + { + name: 'tenant', + alias: 't', + type: String, + description: 'The unique ID of tenant', + }, + { + name: 'allTenants', + alias: 'a', + type: Boolean, + defaultValue: false, + description: 'Set this flag to merge similar organizations for all tenants.', + }, + { + name: 'similarityThreshold', + alias: 's', + type: String, + defaultValue: false, + description: + 'Similarity threshold of organization merge suggestions. Suggestions lower than this value will not be merged. Defaults to 0.95', + }, + { + name: 'hardLimit', + alias: 'l', + type: String, + defaultValue: false, + description: `Hard limit for # of organizations that'll be merged. Mostly a flag for testing purposes.`, + }, + { + name: 'help', + alias: 'h', + type: Boolean, + description: 'Print this usage guide.', + }, +] +const sections = [ + { + content: banner, + raw: true, + }, + { + header: 'Merge organizations with similarity higher than given threshold.', + content: 'Merge organizations with similarity higher than given threshold.', + }, + { + header: 'Options', + optionList: options, + }, +] + +const usage = commandLineUsage(sections) +const parameters = commandLineArgs(options) + +if (parameters.help || (!parameters.tenant && !parameters.allTenants)) { + console.log(usage) +} else { + setImmediate(async () => { + const options = await SequelizeRepository.getDefaultIRepositoryOptions() + + let tenantIds + + if (parameters.allTenants) { + tenantIds = (await TenantService._findAndCountAllForEveryUser({})).rows.map((t) => t.id) + } else if (parameters.tenant) { + tenantIds = parameters.tenant.split(',') + } else { + tenantIds = [] + } + + for (const tenantId of tenantIds) { + const userContext: IRepositoryOptions = await getUserContext(tenantId) + const orgService = new OrganizationService(userContext) + + let hasMoreData = true + let counter = 0 + + while (hasMoreData) { + // find organization merge suggestions of tenant + const result = await options.database.sequelize.query( + ` + SELECT + "ot"."organizationId", + "ot"."toMergeId", + "ot".similarity, + "ot".status, + "org1"."displayName" AS "orgDisplayName", + "org2"."displayName" AS "mergeDisplayName" + FROM + "organizationToMerge" "ot" + LEFT JOIN + "organizations" "org1" + ON + "ot"."organizationId" = "org1"."id" + LEFT JOIN + "organizations" "org2" + ON + "ot"."toMergeId" = "org2"."id" + WHERE + ("ot".similarity > :similarityThreshold) AND + ("org1"."displayName" ilike "org2"."displayName") AND + ("org1"."tenantId" = :tenantId) AND + ("org2"."tenantId" = :tenantId) + ORDER BY + "ot".similarity DESC + LIMIT 100 + OFFSET :offset;`, + { + replacements: { + similarityThreshold: parameters.similarityThreshold || 0.95, + offset: 0, + tenantId, + }, + type: QueryTypes.SELECT, + }, + ) + + if (result.length === 0) { + hasMoreData = false + } else { + for (const row of result) { + try { + console.log( + `Merging [${row.organizationId}] "${row.orgDisplayName}" into ${row.toMergeId} "${row.mergeDisplayName}"...`, + ) + await MergeActionsRepository.add( + MergeActionType.ORG, + row.organizationId, + row.toMergeId, + userContext, + ) + await orgService.mergeSync(row.organizationId, row.toMergeId) + } catch (err) { + console.log('Error merging organizations - continuing with the rest', err) + await MergeActionsRepository.setState( + MergeActionType.ORG, + row.organizationId, + row.toMergeId, + MergeActionState.ERROR, + userContext, + ) + } + + if (parameters.hardLimit && counter >= parameters.hardLimit) { + console.log(`Hard limit of ${parameters.hardLimit} reached. Exiting...`) + process.exit(0) + } + + counter += 1 + } + } + } + } + + process.exit(0) + }) +} diff --git a/backend/src/bin/scripts/process-integration.ts b/backend/src/bin/scripts/process-integration.ts deleted file mode 100644 index 499571d6bf..0000000000 --- a/backend/src/bin/scripts/process-integration.ts +++ /dev/null @@ -1,210 +0,0 @@ -import { processPaginated, singleOrDefault } from '@crowd/common' -import { INTEGRATION_SERVICES } from '@crowd/integrations' -import { getServiceLogger } from '@crowd/logging' -import commandLineArgs from 'command-line-args' -import commandLineUsage from 'command-line-usage' -import * as fs from 'fs' -import path from 'path' -import { IntegrationRunState } from '@crowd/types' -import IntegrationRepository from '../../database/repositories/integrationRepository' -import IntegrationRunRepository from '../../database/repositories/integrationRunRepository' -import SequelizeRepository from '../../database/repositories/sequelizeRepository' -import { getIntegrationRunWorkerEmitter } from '../../serverless/utils/serviceSQS' -import { sendNodeWorkerMessage } from '../../serverless/utils/nodeWorkerSQS' -import { NodeWorkerIntegrationProcessMessage } from '../../types/mq/nodeWorkerIntegrationProcessMessage' - -/* eslint-disable no-console */ - -const banner = fs.readFileSync(path.join(__dirname, 'banner.txt'), 'utf8') - -const log = getServiceLogger() - -const options = [ - { - name: 'integration', - alias: 'i', - typeLabel: '{underline integrationId}', - type: String, - description: - 'The unique ID of integration that you would like to process. Use comma delimiter when sending multiple integrations.', - }, - { - name: 'onboarding', - alias: 'o', - description: 'Process integration as if it was onboarding.', - type: Boolean, - defaultValue: false, - }, - { - name: 'disableFiringCrowdWebhooks', - alias: 'd', - typeLabel: '{underline disableFiringCrowdWebhooks}', - type: Boolean, - defaultOption: false, - description: 'Should it disable firing outgoing crowd webhooks?', - }, - { - name: 'platform', - alias: 'p', - description: 'The platform for which we should run all integrations.', - }, - { - name: 'help', - alias: 'h', - type: Boolean, - description: 'Print this usage guide.', - }, -] -const sections = [ - { - content: banner, - raw: true, - }, - { - header: 'Process Integration', - content: 'Trigger processing of integrations.', - }, - { - header: 'Options', - optionList: options, - }, -] - -const usage = commandLineUsage(sections) -const parameters = commandLineArgs(options) - -const triggerIntegrationRun = async ( - runRepo: IntegrationRunRepository, - tenantId: string, - integrationId: string, - onboarding: boolean, - fireCrowdWebhooks: boolean, -) => { - const existingRun = await runRepo.findLastProcessingRun(integrationId) - - if (existingRun && existingRun.onboarding) { - log.error('Integration is already processing, skipping!') - return - } - - log.info( - { integrationId, onboarding }, - 'Integration found - creating a new run in the old framework!', - ) - const run = await runRepo.create({ - integrationId, - tenantId, - onboarding, - state: IntegrationRunState.PENDING, - }) - - log.info( - { integrationId, onboarding }, - 'Triggering SQS message for the old framework integration!', - ) - await sendNodeWorkerMessage( - tenantId, - new NodeWorkerIntegrationProcessMessage(run.id, null, fireCrowdWebhooks), - ) -} - -const triggerNewIntegrationRun = async ( - tenantId: string, - integrationId: string, - platform: string, - onboarding: boolean, -) => { - log.info( - { integrationId, onboarding }, - 'Triggering SQS message for the new framework integration!', - ) - - const emitter = await getIntegrationRunWorkerEmitter() - await emitter.triggerIntegrationRun(tenantId, platform, integrationId, onboarding) -} - -if (parameters.help || (!parameters.integration && !parameters.platform)) { - console.log(usage) -} else { - setImmediate(async () => { - const onboarding = parameters.onboarding - const options = await SequelizeRepository.getDefaultIRepositoryOptions() - - const fireCrowdWebhooks = !parameters.disableFiringCrowdWebhooks - - const runRepo = new IntegrationRunRepository(options) - - if (parameters.platform) { - let inNewFramework = false - - if (singleOrDefault(INTEGRATION_SERVICES, (s) => s.type === parameters.platform)) { - inNewFramework = true - } - - await processPaginated( - async (page) => IntegrationRepository.findAllActive(parameters.platform, page, 10), - async (integrations) => { - for (const i of integrations) { - const integration = i as any - - if (inNewFramework) { - await triggerNewIntegrationRun( - integration.tenantId, - integration.id, - integration.platform, - onboarding, - ) - } else { - await triggerIntegrationRun( - runRepo, - integration.tenantId, - integration.id, - onboarding, - fireCrowdWebhooks, - ) - } - } - }, - ) - } else { - const integrationIds = parameters.integration.split(',') - for (const integrationId of integrationIds) { - const integration = await options.database.integration.findOne({ - where: { id: integrationId }, - }) - - if (!integration) { - log.error({ integrationId }, 'Integration not found!') - process.exit(1) - } else { - log.info({ integrationId, onboarding }, 'Integration found - triggering SQS message!') - - let inNewFramework = false - - if (singleOrDefault(INTEGRATION_SERVICES, (s) => s.type === integration.platform)) { - inNewFramework = true - } - - if (inNewFramework) { - await triggerNewIntegrationRun( - integration.tenantId, - integration.id, - integration.platform, - onboarding, - ) - } else { - await triggerIntegrationRun( - runRepo, - integration.tenantId, - integration.id, - onboarding, - fireCrowdWebhooks, - ) - } - } - } - } - - process.exit(0) - }) -} diff --git a/backend/src/bin/scripts/process-stream.ts b/backend/src/bin/scripts/process-stream.ts deleted file mode 100644 index a207c14e6f..0000000000 --- a/backend/src/bin/scripts/process-stream.ts +++ /dev/null @@ -1,82 +0,0 @@ -import commandLineArgs from 'command-line-args' -import commandLineUsage from 'command-line-usage' -import * as fs from 'fs' -import path from 'path' -import { getServiceLogger } from '@crowd/logging' -import SequelizeRepository from '../../database/repositories/sequelizeRepository' -import { sendNodeWorkerMessage } from '../../serverless/utils/nodeWorkerSQS' -import { NodeWorkerIntegrationProcessMessage } from '../../types/mq/nodeWorkerIntegrationProcessMessage' -import IntegrationRunRepository from '../../database/repositories/integrationRunRepository' -import IntegrationStreamRepository from '../../database/repositories/integrationStreamRepository' - -/* eslint-disable no-console */ - -const banner = fs.readFileSync(path.join(__dirname, 'banner.txt'), 'utf8') - -const log = getServiceLogger() - -const options = [ - { - name: 'stream', - alias: 's', - typeLabel: '{underline streamId}', - type: String, - description: - 'The unique ID of integration stream that you would like to process. Use comma delimiter when sending multiple integration streams.', - }, - { - name: 'help', - alias: 'h', - type: Boolean, - description: 'Print this usage guide.', - }, -] -const sections = [ - { - content: banner, - raw: true, - }, - { - header: 'Process integration stream', - content: 'Trigger processing of integration stream.', - }, - { - header: 'Options', - optionList: options, - }, -] - -const usage = commandLineUsage(sections) -const parameters = commandLineArgs(options) - -if (parameters.help && !parameters.stream) { - console.log(usage) -} else { - setImmediate(async () => { - const options = await SequelizeRepository.getDefaultIRepositoryOptions() - - const streamRepo = new IntegrationStreamRepository(options) - const runRepo = new IntegrationRunRepository(options) - - const streamIds = parameters.stream.split(',') - for (const streamId of streamIds) { - const stream = await streamRepo.findById(streamId) - - if (!stream) { - log.error({ streamId }, 'Integration stream not found!') - process.exit(1) - } else { - log.info({ streamId }, 'Integration stream found! Triggering SQS message!') - - const run = await runRepo.findById(stream.runId) - - await sendNodeWorkerMessage( - run.tenantId, - new NodeWorkerIntegrationProcessMessage(run.id, stream.id), - ) - } - } - - process.exit(0) - }) -} diff --git a/backend/src/bin/scripts/process-webhook.ts b/backend/src/bin/scripts/process-webhook.ts deleted file mode 100644 index 8026b15b9a..0000000000 --- a/backend/src/bin/scripts/process-webhook.ts +++ /dev/null @@ -1,135 +0,0 @@ -import { getServiceLogger } from '@crowd/logging' -import { getRedisClient } from '@crowd/redis' -import commandLineArgs from 'command-line-args' -import commandLineUsage from 'command-line-usage' -import * as fs from 'fs' -import path from 'path' -import { QueryTypes } from 'sequelize' -import { IntegrationProcessor } from '@/serverless/integrations/services/integrationProcessor' -import { REDIS_CONFIG } from '../../conf' -import SequelizeRepository from '../../database/repositories/sequelizeRepository' - -/* eslint-disable no-console */ - -const banner = fs.readFileSync(path.join(__dirname, 'banner.txt'), 'utf8') - -const log = getServiceLogger() - -const options = [ - { - name: 'webhook', - alias: 'w', - typeLabel: '{underline webhookId}', - type: String, - description: - 'The unique ID of webhook that you would like to process. Use comma delimiter when sending multiple webhooks.', - }, - { - name: 'tenant', - alias: 't', - typeLabel: '{underline tenantId}', - type: String, - description: - 'The unique ID of tenant that you would like to process. Use in combination with type.', - }, - { - name: 'type', - alias: 'p', - typeLabel: '{underline type}', - type: String, - description: 'The webhook type to process. Use in combination with tenant.', - }, - { - name: 'help', - alias: 'h', - type: Boolean, - description: 'Print this usage guide.', - }, -] -const sections = [ - { - content: banner, - raw: true, - }, - { - header: 'Process Webhook', - content: 'Trigger processing of webhooks.', - }, - { - header: 'Options', - optionList: options, - }, -] - -const usage = commandLineUsage(sections) -const parameters = commandLineArgs(options) - -if (parameters.help || (!parameters.webhook && (!parameters.tenant || !parameters.type))) { - console.log(usage) -} else { - setImmediate(async () => { - const options = await SequelizeRepository.getDefaultIRepositoryOptions() - const redisEmitter = await getRedisClient(REDIS_CONFIG) - const integrationProcessorInstance = new IntegrationProcessor(options, redisEmitter) - - if (parameters.webhook) { - const webhookIds = parameters.webhook.split(',') - - for (const webhookId of webhookIds) { - log.info({ webhookId }, 'Webhook found - processing!') - await integrationProcessorInstance.processWebhook(webhookId, true, true) - } - } else if (parameters.tenant && parameters.type) { - const seq = SequelizeRepository.getSequelize(options) - - let ids = ( - await seq.query( - ` - select id from "incomingWebhooks" - where state in ('PENDING', 'ERROR') - and "tenantId" = :tenantId and type = :type - order by id - limit 100 - `, - { - type: QueryTypes.SELECT, - replacements: { - tenantId: parameters.tenant, - type: parameters.type, - }, - }, - ) - ).map((r) => (r as any).id) - - while (ids.length > 0) { - for (const webhookId of ids) { - log.info({ webhookId }, 'Webhook found - processing!') - await integrationProcessorInstance.processWebhook(webhookId, true, true) - } - - ids = ( - await seq.query( - ` - select id from "incomingWebhooks" - where state in ('PENDING', 'ERROR') - and "tenantId" = :tenantId and type = :type - and id > :id - order by id - limit 100 - `, - { - type: QueryTypes.SELECT, - replacements: { - tenantId: parameters.tenant, - type: parameters.type, - id: ids[ids.length - 1], - }, - }, - ) - ).map((r) => (r as any).id) - } - } - - process.exit(0) - }) -} diff --git a/backend/src/bin/scripts/purge-tenants-and-data.ts b/backend/src/bin/scripts/purge-tenants-and-data.ts new file mode 100644 index 0000000000..5b6b82be68 --- /dev/null +++ b/backend/src/bin/scripts/purge-tenants-and-data.ts @@ -0,0 +1,163 @@ +import commandLineArgs from 'command-line-args' +import commandLineUsage from 'command-line-usage' +import * as fs from 'fs' +import path from 'path' +import { QueryTypes } from 'sequelize' +import { getServiceLogger } from '@crowd/logging' +import { databaseInit } from '@/database/databaseConnection' + +/* eslint-disable no-continue */ +/* eslint-disable @typescript-eslint/no-loop-func */ + +const banner = fs.readFileSync(path.join(__dirname, 'banner.txt'), 'utf8') + +const options = [ + { + name: 'tenantIds', + alias: 't', + type: String, + description: + 'Tenants to be excluded from the data purging process. IDs should be comma-separated list.', + }, + { + name: 'help', + alias: 'h', + type: Boolean, + description: 'Print this usage guide.', + }, +] +const sections = [ + { + content: banner, + raw: true, + }, + { + header: 'Purge tenants and their data', + content: 'Purge tenants and their data whose trial period is over.', + }, + { + header: 'Options', + optionList: options, + }, +] + +const usage = commandLineUsage(sections) +const parameters = commandLineArgs(options) + +const log = getServiceLogger() + +async function purgeTenantsAndData(): Promise { + // initialize database with 15 minutes query timeout + const prodDb = await databaseInit(1000 * 60 * 15, true) + + let count = 0 + let purgeableTenants + + log.info('Querying database for tenants where trialEndsAt exists and trial period is over.') + + const doNotPurgeTenantIds = parameters.tenantIds.split(',') + + purgeableTenants = await prodDb.sequelize.query( + ` + select id + from tenants + where "trialEndsAt" is not null and "trialEndsAt" < now()`, + { + type: QueryTypes.SELECT, + }, + ) + + purgeableTenants = purgeableTenants.filter((t) => !doNotPurgeTenantIds.includes(t.id)) + + log.info(`Found ${purgeableTenants.length} tenants to purge!`) + + const tables = [ + 'memberSegments', + 'organizationSegments', + 'microservices', + 'conversations', + 'activities', + 'githubRepos', + 'integrations', + 'reports', + 'settings', + 'widgets', + 'recurringEmailsHistory', + 'eagleEyeContents', + 'members', + 'memberAttributeSettings', + 'tasks', + 'organizationCacheLinks', + 'organizations', + ] + + for (const tenant of purgeableTenants) { + const transaction = await prodDb.sequelize.transaction() + try { + for (const table of tables) { + // The 'organizationCacheLinks' table has a foreign key constraint on 'organizations' table. + // So, before deleting any record from 'organizations', we need to delete the corresponding records from 'organizationCacheLinks'. + if (table === 'organizationCacheLinks') { + await prodDb.sequelize.query( + ` + delete from "${table}" + where "organizationId" IN + (select id + from organizations + where "tenantId" = :tenantId)`, + { + replacements: { tenantId: tenant.id }, + type: QueryTypes.DELETE, + transaction, + }, + ) + } else { + await prodDb.sequelize.query( + ` + delete from "${table}" + where "tenantId" = :tenantId`, + { + replacements: { tenantId: tenant.id }, + type: QueryTypes.DELETE, + transaction, + }, + ) + } + } + + // remove tenant from tenants table + await prodDb.sequelize.query( + ` + delete from tenants + where id = :tenantId`, + { + replacements: { tenantId: tenant.id }, + type: QueryTypes.DELETE, + transaction, + }, + ) + + await transaction.commit() + + count++ + log.info(`Purged ${count}/${purgeableTenants.length} tenants!`) + } catch (error) { + await transaction.rollback() + log.error(`Error purging tenants and their data: ${error.message}`) + process.exit(1) + } + } + + log.info('Revoked access and purged data for free tenants!') +} + +if (parameters.help) { + // eslint-disable-next-line no-console + console.log(usage) +} else { + setImmediate(async () => { + log.info('Starting purging tenants with expired trial period...') + await purgeTenantsAndData() + process.exit(0) + }) +} diff --git a/backend/src/bin/scripts/unleash-init.ts b/backend/src/bin/scripts/unleash-init.ts index cadbc8f818..1ed22c4542 100644 --- a/backend/src/bin/scripts/unleash-init.ts +++ b/backend/src/bin/scripts/unleash-init.ts @@ -1,11 +1,9 @@ -import Sequelize, { QueryTypes } from 'sequelize' -import { getServiceLogger } from '@crowd/logging' import { generateUUIDv1 } from '@crowd/common' -import { FeatureFlag } from '@crowd/types' -import { UnleashContextField } from '../../types/unleashContext' +import { getServiceLogger } from '@crowd/logging' +import { FeatureFlag, PLAN_LIMITS, TenantPlans } from '@crowd/types' +import Sequelize, { QueryTypes } from 'sequelize' import { UNLEASH_CONFIG } from '../../conf' -import Plans from '../../security/plans' -import { PLAN_LIMITS } from '../../feature-flags/isFeatureEnabled' +import { UnleashContextField } from '../../types/unleashContext' /* eslint-disable no-console */ @@ -15,14 +13,14 @@ const constaintConfiguration = { [FeatureFlag.AUTOMATIONS]: [ [ { - values: [Plans.values.scale], + values: [TenantPlans.Scale], inverted: false, operator: 'IN', contextName: 'plan', caseInsensitive: false, }, { - value: PLAN_LIMITS[Plans.values.scale][FeatureFlag.AUTOMATIONS].toString(), + value: PLAN_LIMITS[TenantPlans.Scale][FeatureFlag.AUTOMATIONS].toString(), values: [], inverted: false, operator: 'NUM_LT', @@ -32,14 +30,14 @@ const constaintConfiguration = { ], [ { - values: [Plans.values.growth], + values: [TenantPlans.Growth], inverted: false, operator: 'IN', contextName: 'plan', caseInsensitive: false, }, { - value: PLAN_LIMITS[Plans.values.growth][FeatureFlag.AUTOMATIONS].toString(), + value: PLAN_LIMITS[TenantPlans.Growth][FeatureFlag.AUTOMATIONS].toString(), values: [], inverted: false, operator: 'NUM_LT', @@ -49,14 +47,14 @@ const constaintConfiguration = { ], [ { - values: [Plans.values.essential], + values: [TenantPlans.Essential], inverted: false, operator: 'IN', contextName: 'plan', caseInsensitive: false, }, { - value: PLAN_LIMITS[Plans.values.essential][FeatureFlag.AUTOMATIONS].toString(), + value: PLAN_LIMITS[TenantPlans.Essential][FeatureFlag.AUTOMATIONS].toString(), values: [], inverted: false, operator: 'NUM_LT', @@ -68,14 +66,14 @@ const constaintConfiguration = { [FeatureFlag.CSV_EXPORT]: [ [ { - values: [Plans.values.scale], + values: [TenantPlans.Scale], inverted: false, operator: 'IN', contextName: 'plan', caseInsensitive: false, }, { - value: PLAN_LIMITS[Plans.values.scale][FeatureFlag.CSV_EXPORT].toString(), + value: PLAN_LIMITS[TenantPlans.Scale][FeatureFlag.CSV_EXPORT].toString(), values: [], inverted: false, operator: 'NUM_LT', @@ -85,14 +83,14 @@ const constaintConfiguration = { ], [ { - values: [Plans.values.growth], + values: [TenantPlans.Growth], inverted: false, operator: 'IN', contextName: 'plan', caseInsensitive: false, }, { - value: PLAN_LIMITS[Plans.values.growth][FeatureFlag.CSV_EXPORT].toString(), + value: PLAN_LIMITS[TenantPlans.Growth][FeatureFlag.CSV_EXPORT].toString(), values: [], inverted: false, operator: 'NUM_LT', @@ -102,14 +100,14 @@ const constaintConfiguration = { ], [ { - values: [Plans.values.essential], + values: [TenantPlans.Essential], inverted: false, operator: 'IN', contextName: 'plan', caseInsensitive: false, }, { - value: PLAN_LIMITS[Plans.values.essential][FeatureFlag.CSV_EXPORT].toString(), + value: PLAN_LIMITS[TenantPlans.Essential][FeatureFlag.CSV_EXPORT].toString(), values: [], inverted: false, operator: 'NUM_LT', @@ -121,7 +119,7 @@ const constaintConfiguration = { [FeatureFlag.EAGLE_EYE]: [ [ { - values: [Plans.values.growth, Plans.values.eagleEye, Plans.values.scale], + values: [TenantPlans.Growth, TenantPlans.EagleEye, TenantPlans.Scale], inverted: false, operator: 'IN', contextName: 'plan', @@ -133,7 +131,7 @@ const constaintConfiguration = { [FeatureFlag.LINKEDIN]: [ [ { - values: [Plans.values.growth, Plans.values.scale], + values: [TenantPlans.Growth, TenantPlans.Scale], inverted: false, operator: 'IN', contextName: 'plan', @@ -144,7 +142,7 @@ const constaintConfiguration = { [FeatureFlag.HUBSPOT]: [ [ { - values: [Plans.values.scale], + values: [TenantPlans.Scale], inverted: false, operator: 'IN', contextName: 'plan', @@ -155,14 +153,14 @@ const constaintConfiguration = { [FeatureFlag.MEMBER_ENRICHMENT]: [ [ { - values: [Plans.values.scale], + values: [TenantPlans.Scale], inverted: false, operator: 'IN', contextName: 'plan', caseInsensitive: false, }, { - value: PLAN_LIMITS[Plans.values.scale][FeatureFlag.MEMBER_ENRICHMENT].toString(), + value: PLAN_LIMITS[TenantPlans.Scale][FeatureFlag.MEMBER_ENRICHMENT].toString(), values: [], inverted: false, operator: 'NUM_LT', @@ -172,14 +170,14 @@ const constaintConfiguration = { ], [ { - values: [Plans.values.growth], + values: [TenantPlans.Growth], inverted: false, operator: 'IN', contextName: 'plan', caseInsensitive: false, }, { - value: PLAN_LIMITS[Plans.values.growth][FeatureFlag.MEMBER_ENRICHMENT].toString(), + value: PLAN_LIMITS[TenantPlans.Growth][FeatureFlag.MEMBER_ENRICHMENT].toString(), values: [], inverted: false, operator: 'NUM_LT', @@ -191,14 +189,14 @@ const constaintConfiguration = { [FeatureFlag.ORGANIZATION_ENRICHMENT]: [ [ { - values: [Plans.values.scale], + values: [TenantPlans.Scale], inverted: false, operator: 'IN', contextName: 'plan', caseInsensitive: false, }, { - value: PLAN_LIMITS[Plans.values.scale][FeatureFlag.ORGANIZATION_ENRICHMENT].toString(), + value: PLAN_LIMITS[TenantPlans.Scale][FeatureFlag.ORGANIZATION_ENRICHMENT].toString(), values: [], inverted: false, operator: 'NUM_LT', @@ -208,14 +206,14 @@ const constaintConfiguration = { ], [ { - values: [Plans.values.growth], + values: [TenantPlans.Growth], inverted: false, operator: 'IN', contextName: 'plan', caseInsensitive: false, }, { - value: PLAN_LIMITS[Plans.values.growth][FeatureFlag.ORGANIZATION_ENRICHMENT].toString(), + value: PLAN_LIMITS[TenantPlans.Growth][FeatureFlag.ORGANIZATION_ENRICHMENT].toString(), values: [], inverted: false, operator: 'NUM_LT', @@ -226,15 +224,80 @@ const constaintConfiguration = { ], [FeatureFlag.SEGMENTS]: [], + // temporal + [FeatureFlag.TEMPORAL_MEMBERS_ENRICHMENT]: [ + [ + { + values: [TenantPlans.Scale, TenantPlans.Enterprise], + inverted: false, + operator: 'IN', + contextName: 'plan', + caseInsensitive: false, + }, + ], + ], + + [FeatureFlag.TEMPORAL_MEMBER_MERGE_SUGGESTIONS]: [ + [ + { + values: [ + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.Scale, + TenantPlans.Enterprise, + ], + inverted: false, + operator: 'IN', + contextName: 'plan', + caseInsensitive: false, + }, + ], + ], + [FeatureFlag.SYNCHRONOUS_OPENSEARCH_UPDATES]: [ [ { values: [ - Plans.values.scale, - Plans.values.eagleEye, - Plans.values.enterprise, - Plans.values.essential, - Plans.values.growth, + TenantPlans.Scale, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Essential, + TenantPlans.Growth, + ], + inverted: false, + operator: 'IN', + contextName: 'plan', + caseInsensitive: false, + }, + ], + ], + + [FeatureFlag.SERVE_PROFILES_OPENSEARCH]: [ + [ + { + values: [ + TenantPlans.Scale, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Essential, + TenantPlans.Growth, + ], + inverted: false, + operator: 'IN', + contextName: 'plan', + caseInsensitive: false, + }, + ], + ], + [FeatureFlag.TEMPORAL_ORGANIZATION_ENRICHMENT]: [ + [ + { + values: [ + TenantPlans.Scale, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Essential, + TenantPlans.Growth, ], inverted: false, operator: 'IN', diff --git a/backend/src/bin/worker/integrations.ts b/backend/src/bin/worker/integrations.ts deleted file mode 100644 index 387de96fa8..0000000000 --- a/backend/src/bin/worker/integrations.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { getRedisClient } from '@crowd/redis' -import { Logger } from '@crowd/logging' -import { REDIS_CONFIG } from '../../conf' -import SequelizeRepository from '../../database/repositories/sequelizeRepository' -import { IntegrationProcessor } from '../../serverless/integrations/services/integrationProcessor' -import { IServiceOptions } from '../../services/IServiceOptions' -import { NodeWorkerIntegrationProcessMessage } from '../../types/mq/nodeWorkerIntegrationProcessMessage' -import { NodeWorkerProcessWebhookMessage } from '../../types/mq/nodeWorkerProcessWebhookMessage' - -let integrationProcessorInstance: IntegrationProcessor - -async function getIntegrationProcessor(logger: Logger): Promise { - if (integrationProcessorInstance) return integrationProcessorInstance - - const options: IServiceOptions = { - ...(await SequelizeRepository.getDefaultIRepositoryOptions()), - log: logger, - } - - const redisEmitter = await getRedisClient(REDIS_CONFIG) - - integrationProcessorInstance = new IntegrationProcessor(options, redisEmitter) - - return integrationProcessorInstance -} - -export const processIntegration = async ( - msg: NodeWorkerIntegrationProcessMessage, - messageLogger: Logger, -): Promise => { - const processor = await getIntegrationProcessor(messageLogger) - await processor.process(msg) -} - -export const processWebhook = async ( - msg: NodeWorkerProcessWebhookMessage, - messageLogger: Logger, -): Promise => { - const processor = await getIntegrationProcessor(messageLogger) - await processor.processWebhook(msg.webhookId, msg.force, msg.fireCrowdWebhooks) -} diff --git a/backend/src/conf/configTypes.ts b/backend/src/conf/configTypes.ts index 87e91e4886..1bf7cd0d0e 100644 --- a/backend/src/conf/configTypes.ts +++ b/backend/src/conf/configTypes.ts @@ -23,7 +23,7 @@ export interface SQSConfiguration { host?: string port?: number nodejsWorkerQueue: string - nodejsWorkerDelayableQueue: string + nodejsWorkerPriorityQueue: string integrationRunWorkerQueue: string pythonWorkerQueue: string aws: AwsCredentials @@ -92,6 +92,8 @@ export interface PlansConfiguration { stripWebhookSigningSecret: string stripeEagleEyePlanProductId: string stripeGrowthPlanProductId: string + stripeEssentialPlanProductId: string + stripeScalePlanProductId: string } export interface DevtoConfiguration { @@ -254,3 +256,8 @@ export interface IBackendTemporalConfig extends ITemporalConfig { export interface IOpenStatusApiConfig { baseUrl: string } + +export interface IRedditConfig { + clientId: string + clientSecret: string +} diff --git a/backend/src/conf/index.ts b/backend/src/conf/index.ts index dcaa9fc994..3b132b3a98 100644 --- a/backend/src/conf/index.ts +++ b/backend/src/conf/index.ts @@ -38,6 +38,7 @@ import { IBackendTemporalConfig, IOpenStatusApiConfig, GithubTokenConfiguration, + IRedditConfig, } from './configTypes' // TODO-kube @@ -150,3 +151,5 @@ export const SEARCH_SYNC_API_CONFIG: ISearchSyncApiConfig = export const OPEN_STATUS_API_CONFIG: IOpenStatusApiConfig = config.get('openStatusApi') + +export const REDDIT_CONFIG: IRedditConfig = config.get('reddit') diff --git a/backend/src/database/initializers/twitterSourceIdsFixedTimestamps.ts b/backend/src/database/initializers/twitterSourceIdsFixedTimestamps.ts deleted file mode 100644 index dfe74294f0..0000000000 --- a/backend/src/database/initializers/twitterSourceIdsFixedTimestamps.ts +++ /dev/null @@ -1,63 +0,0 @@ -/** - * This script is responsible for regenerating - * sourceIds for twitter follow activities that have timestamp > 1970-01-01 - */ - -import dotenv from 'dotenv' -import dotenvExpand from 'dotenv-expand' -import { getServiceLogger } from '@crowd/logging' -import { PlatformType } from '@crowd/types' -import ActivityService from '../../services/activityService' -import IntegrationService from '../../services/integrationService' -import TenantService from '../../services/tenantService' -import getUserContext from '../utils/getUserContext' -import { IntegrationServiceBase } from '../../serverless/integrations/services/integrationServiceBase' - -const path = require('path') - -const env = dotenv.config({ - path: path.resolve(__dirname, `../../../.env.staging`), -}) - -dotenvExpand.expand(env) - -const log = getServiceLogger() - -async function twitterFollowsFixSourceIdsWithTimestamp() { - const tenants = await TenantService._findAndCountAllForEveryUser({}) - - // for each tenant - for (const t of tenants.rows) { - const tenantId = t.id - // get user context - const userContext = await getUserContext(tenantId) - const integrationService = new IntegrationService(userContext) - - const twitterIntegration = ( - await integrationService.findAndCountAll({ filter: { platform: PlatformType.TWITTER } }) - ).rows[0] - - if (twitterIntegration) { - const actService = new ActivityService(userContext) - - // get activities where timestamp != 1970-01-01, we can query by > 2000-01-01 - const activities = await actService.findAndCountAll({ - filter: { type: 'follow', timestampRange: ['2000-01-01'] }, - }) - - for (const activity of activities.rows) { - log.info({ activity }, 'Activity') - // calculate sourceId with fixed timestamps - const sourceIdRegenerated = IntegrationServiceBase.generateSourceIdHash( - activity.communityMember.username.twitter, - 'follow', - '1970-01-01T00:00:00+00:00', - 'twitter', - ) - await actService.update(activity.id, { sourceId: sourceIdRegenerated }) - } - } - } -} - -twitterFollowsFixSourceIdsWithTimestamp() diff --git a/backend/src/database/migrations/R__cubejs-materialized-views.sql b/backend/src/database/migrations/R__cubejs-materialized-views.sql index efd002d274..f3937ee397 100644 --- a/backend/src/database/migrations/R__cubejs-materialized-views.sql +++ b/backend/src/database/migrations/R__cubejs-materialized-views.sql @@ -1,3 +1,4 @@ +-- Members DROP MATERIALIZED VIEW IF EXISTS mv_members_cube; CREATE MATERIALIZED VIEW IF NOT EXISTS mv_members_cube AS SELECT @@ -13,6 +14,17 @@ SELECT FROM members m ; +CREATE INDEX IF NOT EXISTS mv_members_cube_tenant ON mv_members_cube ("tenantId"); +CREATE INDEX IF NOT EXISTS mv_members_cube_is_bot ON mv_members_cube ("isBot"); +CREATE INDEX IF NOT EXISTS mv_members_cube_is_team_member ON mv_members_cube ("isTeamMember"); +CREATE INDEX IF NOT EXISTS mv_members_cube_is_organization ON mv_members_cube ("isOrganization"); +CREATE INDEX IF NOT EXISTS mv_members_cube_joined_at ON mv_members_cube ("joinedAt"); + + +CREATE UNIQUE INDEX IF NOT EXISTS mv_members_cube_id ON mv_members_cube (id); + + +-- Activities DROP MATERIALIZED VIEW IF EXISTS mv_activities_cube; CREATE MATERIALIZED VIEW IF NOT EXISTS mv_activities_cube AS SELECT @@ -32,11 +44,23 @@ SELECT END::VARCHAR(8) AS "sentimentMood", a."organizationId", a."segmentId", - a."conversationId" + a."conversationId", + a."createdAt" FROM activities a WHERE a."deletedAt" IS NULL ; +CREATE INDEX IF NOT EXISTS mv_activities_cube_timestamp ON mv_activities_cube (timestamp); +CREATE INDEX IF NOT EXISTS mv_activities_cube_platform ON mv_activities_cube (platform); +CREATE INDEX IF NOT EXISTS mv_activities_cube_org_id ON mv_activities_cube ("organizationId"); +CREATE INDEX IF NOT EXISTS mv_activities_cube_segment_id ON mv_activities_cube ("segmentId"); + +CREATE UNIQUE INDEX IF NOT EXISTS mv_activities_cube_id ON mv_activities_cube (id); +CREATE INDEX IF NOT EXISTS mv_activities_cube_tenantId_timestamp_idx ON mv_activities_cube ("tenantId", "timestamp"); +CREATE INDEX mv_activities_cube_member_id_timestamp ON mv_activities_cube ("memberId", timestamp); + + +-- Organizations DROP MATERIALIZED VIEW IF EXISTS mv_organizations_cube; CREATE MATERIALIZED VIEW IF NOT EXISTS mv_organizations_cube AS SELECT @@ -51,6 +75,12 @@ JOIN activities a ON o.id = a."organizationId" GROUP BY o.id ; +CREATE UNIQUE INDEX IF NOT EXISTS mv_organizations_cube_id ON mv_organizations_cube (id); +CREATE INDEX IF NOT EXISTS mv_organizations_cube_tenantId ON mv_organizations_cube ("tenantId"); +CREATE INDEX IF NOT EXISTS mv_organizations_cube_joined_at ON mv_organizations_cube ("earliestJoinedAt"); + + +-- Segments DROP MATERIALIZED VIEW IF EXISTS mv_segments_cube; CREATE MATERIALIZED VIEW IF NOT EXISTS mv_segments_cube AS SELECT @@ -59,11 +89,4 @@ SELECT FROM segments ; -CREATE INDEX IF NOT EXISTS mv_members_cube_tenant ON mv_members_cube ("tenantId"); -CREATE INDEX IF NOT EXISTS mv_activities_cube_timestamp ON mv_activities_cube (timestamp); -CREATE INDEX IF NOT EXISTS mv_activities_cube_org_id ON mv_activities_cube ("organizationId"); - -CREATE UNIQUE INDEX IF NOT EXISTS mv_members_cube_id ON mv_members_cube (id); -CREATE UNIQUE INDEX IF NOT EXISTS mv_activities_cube_id ON mv_activities_cube (id); -CREATE UNIQUE INDEX IF NOT EXISTS mv_organizations_cube_id ON mv_organizations_cube (id); CREATE UNIQUE INDEX IF NOT EXISTS mv_segments_cube_id ON mv_segments_cube (id); diff --git a/backend/src/database/migrations/R__member_segments_mv.sql b/backend/src/database/migrations/R__member_segments_mv.sql new file mode 100644 index 0000000000..0ee80e88f8 --- /dev/null +++ b/backend/src/database/migrations/R__member_segments_mv.sql @@ -0,0 +1,8 @@ +drop materialized view if exists member_segments_mv; + +create materialized view member_segments_mv as +select distinct "memberId", "segmentId", "tenantId" +from activities +where "deletedAt" is null; + +create unique index ix_member_segments_memberid_segmentid on member_segments_mv ("memberId", "segmentId") \ No newline at end of file diff --git a/backend/src/database/migrations/U1701080323__tenant-priority-level.sql b/backend/src/database/migrations/U1701080323__tenant-priority-level.sql new file mode 100644 index 0000000000..595398663d --- /dev/null +++ b/backend/src/database/migrations/U1701080323__tenant-priority-level.sql @@ -0,0 +1,2 @@ +alter table tenants + drop column "priorityLevel"; \ No newline at end of file diff --git a/backend/src/database/migrations/U1702035391__track-manual-org-changes.sql b/backend/src/database/migrations/U1702035391__track-manual-org-changes.sql new file mode 100644 index 0000000000..da2fada1db --- /dev/null +++ b/backend/src/database/migrations/U1702035391__track-manual-org-changes.sql @@ -0,0 +1,2 @@ +alter table organizations + drop column "manuallyChangedFields"; diff --git a/backend/src/database/migrations/U1702549602__optionalPlan.sql b/backend/src/database/migrations/U1702549602__optionalPlan.sql new file mode 100644 index 0000000000..810b163254 --- /dev/null +++ b/backend/src/database/migrations/U1702549602__optionalPlan.sql @@ -0,0 +1 @@ +ALTER TABLE public."tenants" ALTER COLUMN "plan" SET NOT NULL; diff --git a/backend/src/database/migrations/U1702983814__channel-index.sql b/backend/src/database/migrations/U1702983814__channel-index.sql new file mode 100644 index 0000000000..aa714c147e --- /dev/null +++ b/backend/src/database/migrations/U1702983814__channel-index.sql @@ -0,0 +1,3 @@ +DROP INDEX CONCURRENTLY IF EXISTS ix_unique_activities_tenantid_platform_type_sourceid_segmentid_channel; +CREATE UNIQUE INDEX CONCURRENTLY IF NOT EXISTS activities_tenant_segment_source_id_idx ON activities ("tenantId", "segmentId", "sourceId"); +CREATE UNIQUE INDEX CONCURRENTLY IF NOT EXISTS ix_unique_activities_tenantid_platform_type_sourceid_segmentid ON activities ("tenantId", platform, type, "sourceId", "segmentId"); diff --git a/backend/src/database/migrations/U1703748504__org-identities.sql b/backend/src/database/migrations/U1703748504__org-identities.sql new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/backend/src/database/migrations/U1703748504__org-identities.sql @@ -0,0 +1 @@ + diff --git a/backend/src/database/migrations/U1704204841__memberMergeSuggestionsAddActivityEstimate.sql b/backend/src/database/migrations/U1704204841__memberMergeSuggestionsAddActivityEstimate.sql new file mode 100644 index 0000000000..e063049335 --- /dev/null +++ b/backend/src/database/migrations/U1704204841__memberMergeSuggestionsAddActivityEstimate.sql @@ -0,0 +1 @@ +alter table "memberToMerge" drop column "activityEstimate"; \ No newline at end of file diff --git a/backend/src/database/migrations/U1704365919__fix-member-joined-at.sql b/backend/src/database/migrations/U1704365919__fix-member-joined-at.sql new file mode 100644 index 0000000000..e69de29bb2 diff --git a/backend/src/database/migrations/U1704395824__memberMergeSuggestionsLastGeneratedAt.sql b/backend/src/database/migrations/U1704395824__memberMergeSuggestionsLastGeneratedAt.sql new file mode 100644 index 0000000000..87c5849f6d --- /dev/null +++ b/backend/src/database/migrations/U1704395824__memberMergeSuggestionsLastGeneratedAt.sql @@ -0,0 +1 @@ +alter table "tenants" drop column "memberMergeSuggestionsLastGeneratedAt"; \ No newline at end of file diff --git a/backend/src/database/migrations/U1704923216__dashboardCacheLastRefreshedAt.sql b/backend/src/database/migrations/U1704923216__dashboardCacheLastRefreshedAt.sql new file mode 100644 index 0000000000..eb19081fcc --- /dev/null +++ b/backend/src/database/migrations/U1704923216__dashboardCacheLastRefreshedAt.sql @@ -0,0 +1 @@ +alter table "segments" drop column "dashboardCacheLastRefreshedAt"; \ No newline at end of file diff --git a/backend/src/database/migrations/U1705060063__org-cache-identities-unique-key.sql b/backend/src/database/migrations/U1705060063__org-cache-identities-unique-key.sql new file mode 100644 index 0000000000..e69de29bb2 diff --git a/backend/src/database/migrations/U1706692519__org-cache-identity-unique-name.sql b/backend/src/database/migrations/U1706692519__org-cache-identity-unique-name.sql new file mode 100644 index 0000000000..e69de29bb2 diff --git a/backend/src/database/migrations/V1701080323__tenant-priority-level.sql b/backend/src/database/migrations/V1701080323__tenant-priority-level.sql new file mode 100644 index 0000000000..5b7461bdbe --- /dev/null +++ b/backend/src/database/migrations/V1701080323__tenant-priority-level.sql @@ -0,0 +1,2 @@ +alter table tenants + add column "priorityLevel" varchar(255); \ No newline at end of file diff --git a/backend/src/database/migrations/V1702035391__track-manual-org-changes.sql b/backend/src/database/migrations/V1702035391__track-manual-org-changes.sql new file mode 100644 index 0000000000..72653660ae --- /dev/null +++ b/backend/src/database/migrations/V1702035391__track-manual-org-changes.sql @@ -0,0 +1,2 @@ +alter table organizations + add column "manuallyChangedFields" text[] null; diff --git a/backend/src/database/migrations/V1702549602__optionalPlan.sql b/backend/src/database/migrations/V1702549602__optionalPlan.sql new file mode 100644 index 0000000000..5432c8feff --- /dev/null +++ b/backend/src/database/migrations/V1702549602__optionalPlan.sql @@ -0,0 +1 @@ +ALTER TABLE public."tenants" ALTER COLUMN "plan" DROP NOT NULL; diff --git a/backend/src/database/migrations/V1702983814__channel-index.sql b/backend/src/database/migrations/V1702983814__channel-index.sql new file mode 100644 index 0000000000..5169a84f5e --- /dev/null +++ b/backend/src/database/migrations/V1702983814__channel-index.sql @@ -0,0 +1,3 @@ +DROP INDEX CONCURRENTLY IF EXISTS activities_tenant_segment_source_id_idx; +DROP INDEX CONCURRENTLY IF EXISTS ix_unique_activities_tenantid_platform_type_sourceid_segmentid; +CREATE UNIQUE INDEX CONCURRENTLY IF NOT EXISTS ix_unique_activities_tenantid_platform_type_sourceid_segmentid_channel ON activities ("tenantId", platform, type, "sourceId", "segmentId", channel) \ No newline at end of file diff --git a/backend/src/database/migrations/V1703748504__org-identities.sql b/backend/src/database/migrations/V1703748504__org-identities.sql new file mode 100644 index 0000000000..967bad1e5d --- /dev/null +++ b/backend/src/database/migrations/V1703748504__org-identities.sql @@ -0,0 +1,131 @@ +create table "organizationCacheIdentities" ( + id uuid not null, + name text not null, + website text null, + + primary key (id, name), + foreign key (id) references "organizationCaches" (id) +); + +create index "ix_organizationCacheIdentities_name" on "organizationCacheIdentities" (name); +create index "ix_organizationCacheIdentities_website" on "organizationCacheIdentities" (website); + +alter table "organizationCaches" + rename column name to "oldName"; + +alter table "organizationCaches" + rename column website to "oldWebsite"; + +alter table "organizationCaches" + alter column "oldName" drop not null, + alter column "oldWebsite" drop not null; + +-- fill organizationCacheIdentities table with existing data (for caches without website because for those we need a better logic) +insert into "organizationCacheIdentities"(id, name) +select id, "oldName" +from "organizationCaches" +where "oldWebsite" is null; + +-- fill organizationCacheIdentities table with caches that are the only one in the group by website +insert into "organizationCacheIdentities"(id, name, website) +with data as (select count(id) as ids, "oldWebsite" + from "organizationCaches" + where "oldWebsite" is not null + group by "oldWebsite" + having count(id) = 1) +select oc.id, oc."oldName", oc."oldWebsite" +from "organizationCaches" oc + inner join data d on oc."oldWebsite" = d."oldWebsite"; + +create table "organizationCacheLinks" ( + "organizationCacheId" uuid not null, + "organizationId" uuid not null, + + primary key ("organizationCacheId", "organizationId"), + foreign key ("organizationCacheId") references "organizationCaches" (id), + foreign key ("organizationId") references organizations (id) +); + +-- fill the new organizationCacheLinks table +-- first the ones with website match +insert into "organizationCacheLinks"("organizationCacheId", "organizationId") +select oc.id, o.id +from organizations o + inner join "organizationCaches" oc on oc."oldWebsite" = o.website +where o.website is not null + and not exists (select 1 from "organizationCacheLinks" where "organizationId" = o.id); + +-- then the ones with name match +insert into "organizationCacheLinks"("organizationCacheId", "organizationId") +select oc.id, o.id +from organizations o + inner join "organizationCaches" oc on oc."oldName" = o."displayName" +where o."displayName" is not null + and not exists (select 1 from "organizationCacheLinks" where "organizationId" = o.id); + +-- then the ones that are left +do +$$ + declare + cache_id uuid; + org organizations%rowtype; + begin + for org in select * + from organizations o + where not exists (select 1 from "organizationCacheLinks" where "organizationId" = o.id) + and o."displayName" is not null + and length(trim(o."displayName")) > 0 + loop + -- check if we already created a cache + if org.website is not null then + cache_id := (select id from "organizationCaches" where "oldWebsite" = org.website limit 1); + end if; + + if cache_id is null then + cache_id := (select id from "organizationCaches" where "oldName" = org."displayName" limit 1); + end if; + + if cache_id is null then + -- generate id + cache_id := (select uuid_generate_v1()); + -- insert organizationsCaches row + insert into "organizationCaches" (id, description, emails, "phoneNumbers", logo, tags, twitter, linkedin, crunchbase, employees, "revenueRange", "importHash", "createdAt", "updatedAt", location, github, "employeeCountByCountry", type, "geoLocation", size, ticker, headline, profiles, naics, address, industry, founded, "manuallyCreated", "oldName", "oldWebsite") + values (cache_id, org.description, org.emails, org."phoneNumbers", org.logo, org.tags, org.twitter, org.linkedin, org.crunchbase, org.employees, org."revenueRange", org."importHash", org."createdAt", org."createdAt", org.location, org.github, org."employeeCountByCountry", org.type, org."geoLocation", org.size, org.ticker, org.headline, org.profiles, org.naics, org.address, org.industry, org.founded, org."manuallyCreated", org."displayName", org.website); + -- insert organizationCacheIdentities row + insert into "organizationCacheIdentities"(id, name, website) + values (cache_id, org."displayName", org.website); + end if; + + -- update create link between organizations and organizationCaches tables + insert into "organizationCacheLinks"("organizationCacheId", "organizationId") values (cache_id, org.id); + end loop; + end; +$$; + +-- naics column in organizationCaches and organizations is of type jsonb[] +-- which is not really useful for us since we are not using array operators on it to query it anyway +-- it's also much harder to safely update/insert this using a raw query +-- so we are going to change both columns to just a regular jsonb that will contain an array of objects +alter table "organizationCaches" + add column new_naics jsonb; + +update "organizationCaches" +set new_naics = to_jsonb(naics); + +alter table "organizationCaches" + drop column naics; + +alter table "organizationCaches" + rename column new_naics to naics; + +alter table organizations + add column new_naics jsonb; + +update organizations +set new_naics = to_jsonb(naics); + +alter table organizations + drop column naics; + +alter table organizations + rename column new_naics to naics; \ No newline at end of file diff --git a/backend/src/database/migrations/V1704204841__memberMergeSuggestionsAddActivityEstimate.sql b/backend/src/database/migrations/V1704204841__memberMergeSuggestionsAddActivityEstimate.sql new file mode 100644 index 0000000000..85da83ad38 --- /dev/null +++ b/backend/src/database/migrations/V1704204841__memberMergeSuggestionsAddActivityEstimate.sql @@ -0,0 +1,2 @@ +alter table "memberToMerge" +add column "activityEstimate" int null; \ No newline at end of file diff --git a/backend/src/database/migrations/V1704365919__fix-member-joined-at.sql b/backend/src/database/migrations/V1704365919__fix-member-joined-at.sql new file mode 100644 index 0000000000..ab41e713c2 --- /dev/null +++ b/backend/src/database/migrations/V1704365919__fix-member-joined-at.sql @@ -0,0 +1,36 @@ +DO $$ +DECLARE + _member_id UUID; + _first_acitivity TIMESTAMP; +BEGIN + FOR _member_id IN + SELECT id + FROM members + WHERE EXTRACT(YEAR FROM "joinedAt") = 1970 -- those who have the wrong joinedAt + AND EXISTS ( -- yet have at least one activity with a non-1970 timestamp + SELECT 1 + FROM activities a + WHERE a."memberId" = members.id + AND EXTRACT(YEAR FROM a.timestamp) != 1970 + ) + LOOP + RAISE NOTICE 'member_id: %', _member_id; + + -- find the actual first non-1970 activity timestamp + SELECT MIN(a.timestamp) INTO _first_acitivity + FROM activities a + WHERE EXTRACT(YEAR FROM a.timestamp) != 1970 + AND a."memberId" = _member_id; + + IF _first_acitivity IS NULL THEN + CONTINUE; + END IF; + + RAISE NOTICE 'first_acitivity: %', _first_acitivity; + + UPDATE members + SET "joinedAt" = _first_acitivity + WHERE id = _member_id; + END LOOP; +END; +$$; diff --git a/backend/src/database/migrations/V1704395824__memberMergeSuggestionsLastGeneratedAt.sql b/backend/src/database/migrations/V1704395824__memberMergeSuggestionsLastGeneratedAt.sql new file mode 100644 index 0000000000..0d89f2095c --- /dev/null +++ b/backend/src/database/migrations/V1704395824__memberMergeSuggestionsLastGeneratedAt.sql @@ -0,0 +1,2 @@ +alter table "tenants" +add column "memberMergeSuggestionsLastGeneratedAt" timestamp with time zone null; \ No newline at end of file diff --git a/backend/src/database/migrations/V1704923216__dashboardCacheLastRefreshedAt.sql b/backend/src/database/migrations/V1704923216__dashboardCacheLastRefreshedAt.sql new file mode 100644 index 0000000000..9eae562ae9 --- /dev/null +++ b/backend/src/database/migrations/V1704923216__dashboardCacheLastRefreshedAt.sql @@ -0,0 +1,2 @@ +alter table "segments" +add column "dashboardCacheLastRefreshedAt" timestamp with time zone null; \ No newline at end of file diff --git a/backend/src/database/migrations/V1705060063__org-cache-identities-unique-key.sql b/backend/src/database/migrations/V1705060063__org-cache-identities-unique-key.sql new file mode 100644 index 0000000000..d43c4cd069 --- /dev/null +++ b/backend/src/database/migrations/V1705060063__org-cache-identities-unique-key.sql @@ -0,0 +1,2 @@ +alter table "organizationCacheIdentities" + add constraint ix_unique_website_name unique (name, website); \ No newline at end of file diff --git a/backend/src/database/migrations/V1706692519__org-cache-identity-unique-name.sql b/backend/src/database/migrations/V1706692519__org-cache-identity-unique-name.sql new file mode 100644 index 0000000000..8f6a2fb825 --- /dev/null +++ b/backend/src/database/migrations/V1706692519__org-cache-identity-unique-name.sql @@ -0,0 +1,5 @@ +alter table "organizationCacheIdentities" + drop constraint ix_unique_website_name; + +alter table "organizationCacheIdentities" + add constraint ix_unique_name unique (name); \ No newline at end of file diff --git a/backend/src/database/models/organization.ts b/backend/src/database/models/organization.ts index f9002bcd3e..2dab251328 100644 --- a/backend/src/database/models/organization.ts +++ b/backend/src/database/models/organization.ts @@ -108,7 +108,7 @@ export default (sequelize) => { comment: 'A range representing the size of the company.', }, naics: { - type: DataTypes.ARRAY(DataTypes.JSONB), + type: DataTypes.JSONB, allowNull: true, comment: 'industry classifications for a company according to NAICS', }, @@ -221,6 +221,11 @@ export default (sequelize) => { type: DataTypes.JSONB, allowNull: true, }, + manuallyChangedFields: { + type: DataTypes.ARRAY(DataTypes.TEXT), + allowNull: true, + default: [], + }, }, { indexes: [ diff --git a/backend/src/database/models/organizationCache.ts b/backend/src/database/models/organizationCache.ts index 049400d403..440b6ef4a7 100644 --- a/backend/src/database/models/organizationCache.ts +++ b/backend/src/database/models/organizationCache.ts @@ -9,10 +9,6 @@ export default (sequelize) => { defaultValue: DataTypes.UUIDV4, primaryKey: true, }, - name: { - type: DataTypes.TEXT, - allowNull: false, - }, url: { type: DataTypes.TEXT, allowNull: true, @@ -75,10 +71,6 @@ export default (sequelize) => { type: DataTypes.TEXT, allowNull: true, }, - website: { - type: DataTypes.TEXT, - allowNull: true, - }, founded: { type: DataTypes.INTEGER, allowNull: true, @@ -93,7 +85,7 @@ export default (sequelize) => { comment: 'A range representing the size of the company.', }, naics: { - type: DataTypes.ARRAY(DataTypes.JSONB), + type: DataTypes.JSONB, allowNull: true, comment: 'industry classifications for a company according to NAICS', }, diff --git a/backend/src/database/models/tenant.ts b/backend/src/database/models/tenant.ts index b9f27f41ee..66c905108e 100644 --- a/backend/src/database/models/tenant.ts +++ b/backend/src/database/models/tenant.ts @@ -1,6 +1,4 @@ -import Plans from '../../security/plans' - -const plans = Plans.values +import { TenantPlans } from '@crowd/types' export default (sequelize, DataTypes) => { const tenant = sequelize.define( @@ -41,12 +39,20 @@ export default (sequelize, DataTypes) => { }, plan: { type: DataTypes.STRING(255), - allowNull: false, + allowNull: true, validate: { notEmpty: true, - isIn: [[plans.essential, plans.growth, plans.eagleEye, plans.enterprise, plans.scale]], + isIn: [ + [ + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, + ], + ], }, - defaultValue: plans.essential, + defaultValue: TenantPlans.Essential, }, onboardedAt: { diff --git a/backend/src/database/repositories/__tests__/activityRepository.test.ts b/backend/src/database/repositories/__tests__/activityRepository.test.ts deleted file mode 100644 index 1dc727737f..0000000000 --- a/backend/src/database/repositories/__tests__/activityRepository.test.ts +++ /dev/null @@ -1,1765 +0,0 @@ -import { Error404 } from '@crowd/common' -import MemberRepository from '../memberRepository' -import SequelizeTestUtils from '../../utils/sequelizeTestUtils' -import ActivityRepository from '../activityRepository' -import { MemberAttributeName, PlatformType } from '@crowd/types' -import TaskRepository from '../taskRepository' -import MemberAttributeSettingsRepository from '../memberAttributeSettingsRepository' -import MemberAttributeSettingsService from '../../../services/memberAttributeSettingsService' -import { DEFAULT_MEMBER_ATTRIBUTES, UNKNOWN_ACTIVITY_TYPE_DISPLAY } from '@crowd/integrations' -import OrganizationRepository from '../organizationRepository' - -const db = null - -describe('ActivityRepository tests', () => { - beforeEach(async () => { - await SequelizeTestUtils.wipeDatabase(db) - }) - - afterAll((done) => { - // Closing the DB connection allows Jest to exit successfully. - SequelizeTestUtils.closeConnection(db) - done() - }) - - describe('create method', () => { - it('Should create the given activity succesfully', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - const memberCreated = await MemberRepository.create( - { - username: { - [PlatformType.GITHUB]: 'test', - }, - displayName: 'Member 1', - joinedAt: '2020-05-27T15:13:30Z', - }, - mockIRepositoryOptions, - ) - - const activity = { - type: 'activity', - timestamp: '2020-05-27T15:13:30Z', - platform: PlatformType.GITHUB, - attributes: { - replies: 12, - }, - title: 'Title', - body: 'Here', - url: 'https://github.com', - channel: 'channel', - sentiment: { - positive: 0.98, - negative: 0.0, - neutral: 0.02, - mixed: 0.0, - label: 'positive', - sentiment: 0.98, - }, - isContribution: true, - username: 'test', - member: memberCreated.id, - score: 1, - sourceId: '#sourceId1', - } - - const activityCreated = await ActivityRepository.create(activity, mockIRepositoryOptions) - - // Trim the hour part from timestamp so we can atleast test if the day is correct for createdAt and joinedAt - activityCreated.createdAt = activityCreated.createdAt.toISOString().split('T')[0] - activityCreated.updatedAt = activityCreated.updatedAt.toISOString().split('T')[0] - delete activityCreated.member - delete activityCreated.objectMember - - const expectedActivityCreated = { - id: activityCreated.id, - attributes: activity.attributes, - body: 'Here', - type: 'activity', - title: 'Title', - url: 'https://github.com', - channel: 'channel', - sentiment: { - positive: 0.98, - negative: 0.0, - neutral: 0.02, - mixed: 0.0, - label: 'positive', - sentiment: 0.98, - }, - timestamp: new Date('2020-05-27T15:13:30Z'), - platform: PlatformType.GITHUB, - isContribution: true, - score: 1, - username: 'test', - objectMemberUsername: null, - memberId: memberCreated.id, - objectMemberId: null, - createdAt: SequelizeTestUtils.getNowWithoutTime(), - updatedAt: SequelizeTestUtils.getNowWithoutTime(), - deletedAt: null, - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - tasks: [], - createdById: mockIRepositoryOptions.currentUser.id, - updatedById: mockIRepositoryOptions.currentUser.id, - importHash: null, - parent: null, - parentId: null, - sourceId: activity.sourceId, - sourceParentId: null, - conversationId: null, - display: UNKNOWN_ACTIVITY_TYPE_DISPLAY, - organizationId: null, - organization: null, - } - - expect(activityCreated).toStrictEqual(expectedActivityCreated) - }) - - it('Should create a bare-bones activity succesfully', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - const memberCreated = await MemberRepository.create( - { - username: { - [PlatformType.GITHUB]: 'test', - }, - displayName: 'Member 1', - joinedAt: '2020-05-27T15:13:30Z', - }, - mockIRepositoryOptions, - ) - - const activity = { - type: 'activity', - timestamp: '2020-05-27T15:13:30Z', - platform: PlatformType.GITHUB, - member: memberCreated.id, - username: 'test', - sourceId: '#sourceId1', - } - - const activityCreated = await ActivityRepository.create(activity, mockIRepositoryOptions) - - // Trim the hour part from timestamp so we can atleast test if the day is correct for createdAt and joinedAt - activityCreated.createdAt = activityCreated.createdAt.toISOString().split('T')[0] - activityCreated.updatedAt = activityCreated.updatedAt.toISOString().split('T')[0] - delete activityCreated.member - delete activityCreated.objectMember - - const expectedActivityCreated = { - id: activityCreated.id, - attributes: {}, - body: null, - title: null, - url: null, - channel: null, - sentiment: {}, - type: 'activity', - timestamp: new Date('2020-05-27T15:13:30Z'), - platform: PlatformType.GITHUB, - isContribution: false, - score: 2, - username: 'test', - objectMemberUsername: null, - memberId: memberCreated.id, - objectMemberId: null, - tasks: [], - createdAt: SequelizeTestUtils.getNowWithoutTime(), - updatedAt: SequelizeTestUtils.getNowWithoutTime(), - deletedAt: null, - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - createdById: mockIRepositoryOptions.currentUser.id, - updatedById: mockIRepositoryOptions.currentUser.id, - importHash: null, - parent: null, - parentId: null, - sourceId: activityCreated.sourceId, - sourceParentId: null, - conversationId: null, - display: UNKNOWN_ACTIVITY_TYPE_DISPLAY, - organizationId: null, - organization: null, - } - - expect(activityCreated).toStrictEqual(expectedActivityCreated) - }) - - it('Should throw error when no platform given', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - const memberCreated = await MemberRepository.create( - { - username: { - [PlatformType.GITHUB]: 'test', - }, - displayName: 'Member 1', - joinedAt: '2020-05-27T15:13:30Z', - }, - mockIRepositoryOptions, - ) - - const activity = { - type: 'activity', - timestamp: '2020-05-27T15:13:30Z', - attributes: { - replies: 12, - }, - body: 'Here', - isContribution: true, - username: 'test', - member: memberCreated.id, - score: 1, - } - - await expect(() => - ActivityRepository.create(activity, mockIRepositoryOptions), - ).rejects.toThrow() - }) - - it('Should throw error when no type given', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - const memberCreated = await MemberRepository.create( - { - username: { - [PlatformType.GITHUB]: 'test', - }, - displayName: 'Member 1', - joinedAt: '2020-05-27T15:13:30Z', - }, - mockIRepositoryOptions, - ) - - const activity = { - platform: 'activity', - timestamp: '2020-05-27T15:13:30Z', - attributes: { - replies: 12, - }, - username: 'test', - body: 'Here', - isContribution: true, - member: memberCreated.id, - score: 1, - } - - await expect(() => - ActivityRepository.create(activity, mockIRepositoryOptions), - ).rejects.toThrow() - }) - - it('Should throw error when no timestamp given', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - const memberCreated = await MemberRepository.create( - { - username: { - [PlatformType.GITHUB]: 'test', - }, - displayName: 'Member 1', - joinedAt: '2020-05-27T15:13:30Z', - }, - mockIRepositoryOptions, - ) - - const activity = { - platform: PlatformType.GITHUB, - type: 'activity', - attributes: { - replies: 12, - }, - username: 'test', - body: 'Here', - isContribution: true, - member: memberCreated.id, - score: 1, - } - - await expect(() => - ActivityRepository.create(activity, mockIRepositoryOptions), - ).rejects.toThrow() - }) - - it('Should throw error when sentiment is incorrect', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - const memberCreated = await MemberRepository.create( - { - username: { - [PlatformType.GITHUB]: 'test', - }, - displayName: 'Member 1', - joinedAt: '2020-05-27T15:13:30Z', - }, - mockIRepositoryOptions, - ) - - // Incomplete Object - await expect(() => - ActivityRepository.create( - { - type: 'activity', - timestamp: '2020-05-27T15:13:30Z', - platform: PlatformType.GITHUB, - sentiment: { - positive: 1, - sentiment: 'positive', - score: 1, - }, - username: 'test', - member: memberCreated.id, - sourceId: '#sourceId1', - }, - mockIRepositoryOptions, - ), - ).rejects.toThrow() - - // No score - await expect(() => - ActivityRepository.create( - { - type: 'activity', - timestamp: '2020-05-27T15:13:30Z', - platform: PlatformType.GITHUB, - sentiment: { - positive: 0.8, - negative: 0.2, - mixed: 0, - neutral: 0, - sentiment: 'positive', - }, - username: 'test', - member: memberCreated.id, - sourceId: '#sourceId1', - }, - mockIRepositoryOptions, - ), - ).rejects.toThrow() - - // Wrong Sentiment field - await expect(() => - ActivityRepository.create( - { - type: 'activity', - timestamp: '2020-05-27T15:13:30Z', - platform: PlatformType.GITHUB, - sentiment: { - positive: 0.3, - negative: 0.2, - neutral: 0.5, - mixed: 0, - score: 0.1, - sentiment: 'smth', - }, - username: 'test', - member: memberCreated.id, - sourceId: '#sourceId1', - }, - mockIRepositoryOptions, - ), - ).rejects.toThrow() - - // Works with empty object - const created = await ActivityRepository.create( - { - type: 'activity', - timestamp: '2020-05-27T15:13:30Z', - platform: PlatformType.GITHUB, - sentiment: {}, - username: 'test', - member: memberCreated.id, - sourceId: '#sourceId1', - }, - mockIRepositoryOptions, - ) - expect(created.sentiment).toStrictEqual({}) - }) - - it('Should leave allowed HTML tags in body and title', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - const memberCreated = await MemberRepository.create( - { - username: { - [PlatformType.GITHUB]: 'test', - }, - displayName: 'Member 1', - joinedAt: '2020-05-27T15:13:30Z', - }, - mockIRepositoryOptions, - ) - - const activity = { - type: 'activity', - timestamp: '2020-05-27T15:13:30Z', - platform: PlatformType.GITHUB, - body: '

This is some HTML

', - title: '

This is some Title HTML

', - url: 'https://github.com', - channel: 'channel', - isContribution: true, - username: 'test', - member: memberCreated.id, - score: 1, - sourceId: '#sourceId1', - } - - const activityCreated = await ActivityRepository.create(activity, mockIRepositoryOptions) - - // Trim the hour part from timestamp so we can atleast test if the day is correct for createdAt and joinedAt - activityCreated.createdAt = activityCreated.createdAt.toISOString().split('T')[0] - activityCreated.updatedAt = activityCreated.updatedAt.toISOString().split('T')[0] - delete activityCreated.member - delete activityCreated.objectMember - - const expectedActivityCreated = { - id: activityCreated.id, - attributes: {}, - body: '

This is some HTML

', - type: 'activity', - title: '

This is some Title HTML

', - url: 'https://github.com', - channel: 'channel', - sentiment: {}, - timestamp: new Date('2020-05-27T15:13:30Z'), - platform: PlatformType.GITHUB, - isContribution: true, - score: 1, - tasks: [], - username: 'test', - objectMemberUsername: null, - memberId: memberCreated.id, - objectMemberId: null, - createdAt: SequelizeTestUtils.getNowWithoutTime(), - updatedAt: SequelizeTestUtils.getNowWithoutTime(), - deletedAt: null, - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - createdById: mockIRepositoryOptions.currentUser.id, - updatedById: mockIRepositoryOptions.currentUser.id, - importHash: null, - parent: null, - parentId: null, - sourceId: activity.sourceId, - sourceParentId: null, - conversationId: null, - display: UNKNOWN_ACTIVITY_TYPE_DISPLAY, - organizationId: null, - organization: null, - } - - expect(activityCreated).toStrictEqual(expectedActivityCreated) - }) - - it('Should remove script tags in body and title', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - const memberCreated = await MemberRepository.create( - { - username: { - [PlatformType.GITHUB]: 'test', - }, - displayName: 'Member 1', - joinedAt: '2020-05-27T15:13:30Z', - }, - mockIRepositoryOptions, - ) - - const activity = { - type: 'activity', - timestamp: '2020-05-27T15:13:30Z', - platform: PlatformType.GITHUB, - body: "

Malicious

", - title: "

Malicious title

", - url: 'https://github.com', - channel: 'channel', - isContribution: true, - username: 'test', - member: memberCreated.id, - score: 1, - sourceId: '#sourceId1', - } - - const activityCreated = await ActivityRepository.create(activity, mockIRepositoryOptions) - - // Trim the hour part from timestamp so we can atleast test if the day is correct for createdAt and joinedAt - activityCreated.createdAt = activityCreated.createdAt.toISOString().split('T')[0] - activityCreated.updatedAt = activityCreated.updatedAt.toISOString().split('T')[0] - delete activityCreated.member - delete activityCreated.objectMember - - const expectedActivityCreated = { - id: activityCreated.id, - attributes: {}, - body: '

Malicious

', - type: 'activity', - title: '

Malicious title

', - url: 'https://github.com', - channel: 'channel', - sentiment: {}, - tasks: [], - timestamp: new Date('2020-05-27T15:13:30Z'), - platform: PlatformType.GITHUB, - isContribution: true, - score: 1, - username: 'test', - objectMemberUsername: null, - memberId: memberCreated.id, - objectMemberId: null, - createdAt: SequelizeTestUtils.getNowWithoutTime(), - updatedAt: SequelizeTestUtils.getNowWithoutTime(), - deletedAt: null, - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - createdById: mockIRepositoryOptions.currentUser.id, - updatedById: mockIRepositoryOptions.currentUser.id, - importHash: null, - parent: null, - parentId: null, - sourceId: activity.sourceId, - sourceParentId: null, - conversationId: null, - display: UNKNOWN_ACTIVITY_TYPE_DISPLAY, - organizationId: null, - organization: null, - } - - expect(activityCreated).toStrictEqual(expectedActivityCreated) - }) - - it('Should create an activity with tasks succesfully', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - const memberCreated = await MemberRepository.create( - { - username: { - [PlatformType.GITHUB]: 'test', - }, - displayName: 'Member 1', - joinedAt: '2020-05-27T15:13:30Z', - }, - mockIRepositoryOptions, - ) - - const tasks1 = await TaskRepository.create( - { - name: 'task1', - }, - mockIRepositoryOptions, - ) - - const task2 = await TaskRepository.create( - { - name: 'task2', - }, - mockIRepositoryOptions, - ) - - const activity = { - type: 'activity', - timestamp: '2020-05-27T15:13:30Z', - platform: PlatformType.GITHUB, - attributes: { - replies: 12, - }, - title: 'Title', - body: 'Here', - url: 'https://github.com', - channel: 'channel', - sentiment: { - positive: 0.98, - negative: 0.0, - neutral: 0.02, - mixed: 0.0, - label: 'positive', - sentiment: 0.98, - }, - isContribution: true, - username: 'test', - member: memberCreated.id, - score: 1, - tasks: [tasks1.id, task2.id], - sourceId: '#sourceId1', - } - - const activityCreated = await ActivityRepository.create(activity, mockIRepositoryOptions) - - // Trim the hour part from timestamp so we can atleast test if the day is correct for createdAt and joinedAt - expect(activityCreated.tasks.length).toBe(2) - }) - - it('Should create an activity with an organization succesfully', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - const memberCreated = await MemberRepository.create( - { - username: { - [PlatformType.GITHUB]: 'test', - }, - displayName: 'Member 1', - joinedAt: '2020-05-27T15:13:30Z', - }, - mockIRepositoryOptions, - ) - - const org1 = await OrganizationRepository.create( - { - displayName: 'crowd.dev', - }, - mockIRepositoryOptions, - ) - - const activity = { - type: 'activity', - timestamp: '2020-05-27T15:13:30Z', - platform: PlatformType.GITHUB, - attributes: { - replies: 12, - }, - title: 'Title', - body: 'Here', - url: 'https://github.com', - channel: 'channel', - sentiment: { - positive: 0.98, - negative: 0.0, - neutral: 0.02, - mixed: 0.0, - label: 'positive', - sentiment: 0.98, - }, - isContribution: true, - username: 'test', - member: memberCreated.id, - score: 1, - organizationId: org1.id, - sourceId: '#sourceId1', - } - - const activityCreated = await ActivityRepository.create(activity, mockIRepositoryOptions) - - // Trim the hour part from timestamp so we can atleast test if the day is correct for createdAt and joinedAt - expect(activityCreated.organizationId).toEqual(org1.id) - }) - }) - - describe('findById method', () => { - it('Should successfully find created activity by id', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - const memberCreated = await MemberRepository.create( - { - username: { - [PlatformType.GITHUB]: 'test', - }, - displayName: 'Member 1', - joinedAt: '2020-05-27T15:13:30Z', - }, - mockIRepositoryOptions, - ) - - const activity = { - type: 'activity', - timestamp: '2020-05-27T15:13:30Z', - platform: PlatformType.GITHUB, - isContribution: true, - username: 'test', - member: memberCreated.id, - score: 1, - sourceId: '#sourceId1', - } - - const activityCreated = await ActivityRepository.create(activity, mockIRepositoryOptions) - - const expectedActivityFound = { - id: activityCreated.id, - attributes: {}, - body: null, - title: null, - url: null, - channel: null, - sentiment: {}, - type: 'activity', - timestamp: new Date('2020-05-27T15:13:30Z'), - platform: PlatformType.GITHUB, - isContribution: true, - score: 1, - username: 'test', - objectMemberUsername: null, - memberId: memberCreated.id, - objectMemberId: null, - tasks: [], - createdAt: SequelizeTestUtils.getNowWithoutTime(), - updatedAt: SequelizeTestUtils.getNowWithoutTime(), - deletedAt: null, - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - createdById: mockIRepositoryOptions.currentUser.id, - updatedById: mockIRepositoryOptions.currentUser.id, - importHash: null, - parent: null, - parentId: null, - sourceId: activity.sourceId, - sourceParentId: null, - conversationId: null, - display: UNKNOWN_ACTIVITY_TYPE_DISPLAY, - organizationId: null, - organization: null, - } - - const activityFound = await ActivityRepository.findById( - activityCreated.id, - mockIRepositoryOptions, - ) - - // Trim the hour part from timestamp so we can atleast test if the day is correct for createdAt and joinedAt - activityFound.createdAt = activityFound.createdAt.toISOString().split('T')[0] - activityFound.updatedAt = activityFound.updatedAt.toISOString().split('T')[0] - delete activityFound.member - delete activityFound.objectMember - - expect(activityFound).toStrictEqual(expectedActivityFound) - }) - - it('Should throw 404 error when no user found with given id', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - const { randomUUID } = require('crypto') - - await expect(() => - ActivityRepository.findById(randomUUID(), mockIRepositoryOptions), - ).rejects.toThrowError(new Error404()) - }) - }) - - describe('filterIdsInTenant method', () => { - it('Should return the given ids of previously created activity entities', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const memberCreated = await MemberRepository.create( - { - username: { - [PlatformType.GITHUB]: 'test', - }, - displayName: 'Member 1', - joinedAt: '2020-05-27T15:13:30Z', - }, - mockIRepositoryOptions, - ) - - const activity1Returned = await ActivityRepository.create( - { - type: 'activity', - timestamp: '2020-05-27T15:13:30Z', - platform: PlatformType.GITHUB, - username: 'test', - member: memberCreated.id, - sourceId: '#sourceId1', - }, - mockIRepositoryOptions, - ) - - const activity2Returned = await ActivityRepository.create( - { - type: 'activity-2', - timestamp: '2020-06-27T15:13:30Z', - platform: PlatformType.GITHUB, - username: 'test', - member: memberCreated.id, - sourceId: '#sourceId2', - }, - mockIRepositoryOptions, - ) - - const filterIdsReturned = await ActivityRepository.filterIdsInTenant( - [activity1Returned.id, activity2Returned.id], - mockIRepositoryOptions, - ) - - expect(filterIdsReturned).toStrictEqual([activity1Returned.id, activity2Returned.id]) - }) - - it('Should only return the ids of previously created activities and filter random uuids out', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const memberCreated = await MemberRepository.create( - { - username: { - [PlatformType.GITHUB]: 'test', - }, - displayName: 'Member 1', - joinedAt: '2020-05-27T15:13:30Z', - }, - mockIRepositoryOptions, - ) - - const activity3Returned = await ActivityRepository.create( - { - type: 'activity', - timestamp: '2020-05-27T15:13:30Z', - platform: PlatformType.GITHUB, - username: 'test', - member: memberCreated.id, - sourceId: '#sourceId1', - }, - mockIRepositoryOptions, - ) - - const { randomUUID } = require('crypto') - - const filterIdsReturned = await ActivityRepository.filterIdsInTenant( - [activity3Returned.id, randomUUID(), randomUUID()], - mockIRepositoryOptions, - ) - - expect(filterIdsReturned).toStrictEqual([activity3Returned.id]) - }) - - it('Should return an empty array for an irrelevant tenant', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const memberCreated = await MemberRepository.create( - { - username: { - [PlatformType.GITHUB]: 'test', - }, - displayName: 'Member 1', - joinedAt: '2020-05-27T15:13:30Z', - }, - mockIRepositoryOptions, - ) - - const activity4Returned = await ActivityRepository.create( - { - type: 'activity', - timestamp: '2020-05-27T15:13:30Z', - platform: PlatformType.GITHUB, - username: 'test', - member: memberCreated.id, - sourceId: '#sourceId1', - }, - mockIRepositoryOptions, - ) - - // create a new tenant and bind options to it - const mockIRepositoryOptionsIr = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const filterIdsReturned = await ActivityRepository.filterIdsInTenant( - [activity4Returned.id], - mockIRepositoryOptionsIr, - ) - - expect(filterIdsReturned).toStrictEqual([]) - }) - }) - - describe('Activities findOne method', () => { - it('Should return the created activity for a simple query', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const memberCreated = await MemberRepository.create( - { - username: { - [PlatformType.GITHUB]: 'test', - }, - displayName: 'Member 1', - joinedAt: '2020-05-27T15:13:30Z', - }, - mockIRepositoryOptions, - ) - - const activityReturned = await ActivityRepository.create( - { - type: 'activity', - timestamp: '2020-05-27T15:13:30Z', - platform: PlatformType.GITHUB, - isContribution: true, - username: 'test', - member: memberCreated.id, - score: 1, - sourceId: '#sourceId1', - }, - mockIRepositoryOptions, - ) - - const found = await ActivityRepository.findOne({ type: 'activity' }, mockIRepositoryOptions) - - expect(found.id).toStrictEqual(activityReturned.id) - }) - - it('Should return the activity for a complex query', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const memberCreated = await MemberRepository.create( - { - username: { - [PlatformType.GITHUB]: 'test', - }, - displayName: 'Member 1', - joinedAt: '2020-05-27T15:13:30Z', - }, - mockIRepositoryOptions, - ) - - const activityReturned = await ActivityRepository.create( - { - type: 'activity', - timestamp: '2020-05-27T15:13:30Z', - platform: PlatformType.GITHUB, - attributes: { - thread: true, - }, - body: 'Here', - isContribution: true, - username: 'test', - member: memberCreated.id, - score: 1, - sourceId: '#sourceId1', - }, - mockIRepositoryOptions, - ) - - const found = await ActivityRepository.findOne( - { 'attributes.thread': true }, - mockIRepositoryOptions, - ) - - expect(found.id).toStrictEqual(activityReturned.id) - }) - - it('Should return null when non-existent', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const memberCreated = await MemberRepository.create( - { - username: { - [PlatformType.GITHUB]: 'test', - }, - displayName: 'Member 1', - joinedAt: '2020-05-27T15:13:30Z', - }, - mockIRepositoryOptions, - ) - - await ActivityRepository.create( - { - type: 'activity', - timestamp: '2020-05-27T15:13:30Z', - platform: PlatformType.GITHUB, - attributes: { - replies: 12, - }, - body: 'Here', - isContribution: true, - username: 'test', - member: memberCreated.id, - score: 1, - sourceId: '#sourceId1', - }, - mockIRepositoryOptions, - ) - - expect( - await ActivityRepository.findOne({ type: 'notype' }, mockIRepositoryOptions), - ).toBeNull() - }) - }) - - describe('update method', () => { - it('Should succesfully update previously created activity - simple', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const memberCreated = await MemberRepository.create( - { - username: { - [PlatformType.GITHUB]: 'test', - }, - displayName: 'Member 1', - joinedAt: '2020-05-27T15:13:30Z', - }, - mockIRepositoryOptions, - ) - - const activityReturned = await ActivityRepository.create( - { - type: 'activity', - timestamp: '2020-05-27T15:13:30Z', - platform: PlatformType.GITHUB, - attributes: { - replies: 12, - }, - body: 'Here', - isContribution: true, - username: 'test', - member: memberCreated.id, - score: 1, - sourceId: '#sourceId1', - }, - mockIRepositoryOptions, - ) - - const updateFields = { - type: 'activity-new', - platform: PlatformType.GITHUB, - } - - const updatedActivity = await ActivityRepository.update( - activityReturned.id, - updateFields, - mockIRepositoryOptions, - ) - - // check updatedAt field looks ok or not. Should be greater than createdAt - expect(updatedActivity.updatedAt.getTime()).toBeGreaterThan( - updatedActivity.createdAt.getTime(), - ) - - updatedActivity.createdAt = updatedActivity.createdAt.toISOString().split('T')[0] - updatedActivity.updatedAt = updatedActivity.updatedAt.toISOString().split('T')[0] - delete updatedActivity.member - delete updatedActivity.objectMember - - const expectedActivityUpdated = { - id: activityReturned.id, - body: activityReturned.body, - channel: null, - title: null, - sentiment: {}, - url: null, - attributes: activityReturned.attributes, - type: 'activity-new', - timestamp: new Date('2020-05-27T15:13:30Z'), - platform: PlatformType.GITHUB, - isContribution: true, - score: 1, - username: 'test', - objectMemberUsername: null, - memberId: memberCreated.id, - objectMemberId: null, - createdAt: SequelizeTestUtils.getNowWithoutTime(), - updatedAt: SequelizeTestUtils.getNowWithoutTime(), - deletedAt: null, - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - createdById: mockIRepositoryOptions.currentUser.id, - updatedById: mockIRepositoryOptions.currentUser.id, - importHash: null, - tasks: [], - parent: null, - parentId: null, - sourceId: activityReturned.sourceId, - sourceParentId: null, - conversationId: null, - display: UNKNOWN_ACTIVITY_TYPE_DISPLAY, - organizationId: null, - organization: null, - } - - expect(updatedActivity).toStrictEqual(expectedActivityUpdated) - }) - - it('Should succesfully update previously created activity - with member relation', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const memberCreated = await MemberRepository.create( - { - username: { - [PlatformType.GITHUB]: 'test', - }, - displayName: 'Member 1', - joinedAt: '2020-05-27T15:13:30Z', - }, - mockIRepositoryOptions, - ) - - const memberCreated2 = await MemberRepository.create( - { - username: { - [PlatformType.GITHUB]: 'test2', - }, - displayName: 'Member 1', - joinedAt: '2020-05-27T15:13:30Z', - }, - mockIRepositoryOptions, - ) - - const activityReturned = await ActivityRepository.create( - { - type: 'activity', - timestamp: '2020-05-27T15:13:30Z', - platform: PlatformType.GITHUB, - attributes: { - replies: 12, - }, - body: 'Here', - isContribution: true, - username: 'test', - member: memberCreated.id, - score: 1, - sourceId: '#sourceId1', - }, - mockIRepositoryOptions, - ) - - const updateFields = { - type: 'activity-new', - platform: PlatformType.GITHUB, - body: 'There', - title: 'Title', - channel: 'Channel', - url: 'https://www.google.com', - sentiment: { - positive: 0.98, - negative: 0.0, - neutral: 0.02, - mixed: 0.0, - label: 'positive', - sentiment: 0.98, - }, - username: 'test2', - member: memberCreated2.id, - } - - const updatedActivity = await ActivityRepository.update( - activityReturned.id, - updateFields, - mockIRepositoryOptions, - ) - - // check updatedAt field looks ok or not. Should be greater than createdAt - expect(updatedActivity.updatedAt.getTime()).toBeGreaterThan( - updatedActivity.createdAt.getTime(), - ) - - updatedActivity.createdAt = updatedActivity.createdAt.toISOString().split('T')[0] - updatedActivity.updatedAt = updatedActivity.updatedAt.toISOString().split('T')[0] - delete updatedActivity.member - delete updatedActivity.objectMember - - const expectedActivityUpdated = { - id: activityReturned.id, - attributes: activityReturned.attributes, - body: updateFields.body, - channel: updateFields.channel, - title: updateFields.title, - sentiment: updateFields.sentiment, - url: updateFields.url, - type: 'activity-new', - timestamp: new Date('2020-05-27T15:13:30Z'), - tasks: [], - platform: PlatformType.GITHUB, - isContribution: true, - score: 1, - username: 'test2', - objectMemberUsername: null, - memberId: memberCreated2.id, - objectMemberId: null, - createdAt: SequelizeTestUtils.getNowWithoutTime(), - updatedAt: SequelizeTestUtils.getNowWithoutTime(), - deletedAt: null, - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - createdById: mockIRepositoryOptions.currentUser.id, - updatedById: mockIRepositoryOptions.currentUser.id, - importHash: null, - parent: null, - parentId: null, - sourceId: activityReturned.sourceId, - sourceParentId: null, - conversationId: null, - display: UNKNOWN_ACTIVITY_TYPE_DISPLAY, - organizationId: null, - organization: null, - } - - expect(updatedActivity).toStrictEqual(expectedActivityUpdated) - }) - - it('Should succesfully update tasks of an activity', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const memberCreated = await MemberRepository.create( - { - username: { - [PlatformType.GITHUB]: 'test', - }, - displayName: 'Member 1', - joinedAt: '2020-05-27T15:13:30Z', - }, - mockIRepositoryOptions, - ) - - const activityReturned = await ActivityRepository.create( - { - type: 'activity', - timestamp: '2020-05-27T15:13:30Z', - platform: PlatformType.GITHUB, - attributes: { - replies: 12, - }, - body: 'Here', - isContribution: true, - username: 'test', - member: memberCreated.id, - score: 1, - sourceId: '#sourceId1', - }, - mockIRepositoryOptions, - ) - - const tasks1 = await TaskRepository.create( - { - name: 'task1', - }, - mockIRepositoryOptions, - ) - - const task2 = await TaskRepository.create( - { - name: 'task2', - }, - mockIRepositoryOptions, - ) - - const updateFields = { - tasks: [tasks1.id, task2.id], - } - - const updatedActivity = await ActivityRepository.update( - activityReturned.id, - updateFields, - mockIRepositoryOptions, - ) - - expect(updatedActivity.tasks).toHaveLength(2) - expect(updatedActivity.tasks[0].id).toBe(tasks1.id) - expect(updatedActivity.tasks[1].id).toBe(task2.id) - }) - - it('Should update body and title with allowed HTML tags', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const memberCreated = await MemberRepository.create( - { - username: { - [PlatformType.GITHUB]: 'test', - }, - displayName: 'Member 1', - joinedAt: '2020-05-27T15:13:30Z', - }, - mockIRepositoryOptions, - ) - - const activityReturned = await ActivityRepository.create( - { - type: 'activity', - timestamp: '2020-05-27T15:13:30Z', - platform: PlatformType.GITHUB, - attributes: { - replies: 12, - }, - body: 'Here', - isContribution: true, - username: 'test', - member: memberCreated.id, - score: 1, - sourceId: '#sourceId1', - }, - mockIRepositoryOptions, - ) - - const updateFields = { - body: '

This is some HTML

', - title: '

This is some Title HTML

', - } - - const updatedActivity = await ActivityRepository.update( - activityReturned.id, - updateFields, - mockIRepositoryOptions, - ) - - expect(updatedActivity.body).toBe('

This is some HTML

') - expect(updatedActivity.title).toBe('

This is some Title HTML

') - }) - - it('Should sanitize body and title from non-allowed HTML tags', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const memberCreated = await MemberRepository.create( - { - username: { - [PlatformType.GITHUB]: 'test', - }, - displayName: 'Member 1', - joinedAt: '2020-05-27T15:13:30Z', - }, - mockIRepositoryOptions, - ) - - const activityReturned = await ActivityRepository.create( - { - type: 'activity', - timestamp: '2020-05-27T15:13:30Z', - platform: PlatformType.GITHUB, - attributes: { - replies: 12, - }, - body: 'Here', - isContribution: true, - username: 'test', - member: memberCreated.id, - score: 1, - sourceId: '#sourceId1', - }, - mockIRepositoryOptions, - ) - - const updateFields = { - body: "

Malicious

", - title: "

Malicious title

", - } - - const updatedActivity = await ActivityRepository.update( - activityReturned.id, - updateFields, - mockIRepositoryOptions, - ) - - expect(updatedActivity.body).toBe('

Malicious

') - expect(updatedActivity.title).toBe('

Malicious title

') - }) - - it('Should update an activity with an organization succesfully', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - const memberCreated = await MemberRepository.create( - { - username: { - [PlatformType.GITHUB]: 'test', - }, - displayName: 'Member 1', - joinedAt: '2020-05-27T15:13:30Z', - }, - mockIRepositoryOptions, - ) - - const org1 = await OrganizationRepository.create( - { - displayName: 'crowd.dev', - }, - mockIRepositoryOptions, - ) - - const org2 = await OrganizationRepository.create( - { - displayName: 'tesla', - }, - mockIRepositoryOptions, - ) - - const activity = { - type: 'activity', - timestamp: '2020-05-27T15:13:30Z', - platform: PlatformType.GITHUB, - attributes: { - replies: 12, - }, - title: 'Title', - body: 'Here', - url: 'https://github.com', - channel: 'channel', - sentiment: { - positive: 0.98, - negative: 0.0, - neutral: 0.02, - mixed: 0.0, - label: 'positive', - sentiment: 0.98, - }, - isContribution: true, - username: 'test', - member: memberCreated.id, - score: 1, - organizationId: org1.id, - sourceId: '#sourceId1', - } - - const activityCreated = await ActivityRepository.create(activity, mockIRepositoryOptions) - - const activityUpdated = await ActivityRepository.update( - activityCreated.id, - { organizationId: org2.id }, - mockIRepositoryOptions, - ) - - // Trim the hour part from timestamp so we can atleast test if the day is correct for createdAt and joinedAt - expect(activityUpdated.organizationId).toEqual(org2.id) - }) - }) - - describe('filter tests', () => { - it('Positive sentiment filter and sort', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - const memberCreated = await MemberRepository.create( - { - username: { - [PlatformType.GITHUB]: 'test', - }, - displayName: 'Member 1', - joinedAt: '2020-05-27T15:13:30Z', - }, - mockIRepositoryOptions, - ) - - const activity1 = { - type: 'activity', - timestamp: '2020-05-27T15:13:30Z', - platform: PlatformType.GITHUB, - sentiment: { - positive: 0.98, - negative: 0.0, - neutral: 0.02, - mixed: 0.0, - label: 'positive', - sentiment: 0.98, - }, - username: 'test', - member: memberCreated.id, - sourceId: '#sourceId1', - } - - const activity2 = { - type: 'activity', - timestamp: '2020-05-27T15:13:30Z', - platform: PlatformType.GITHUB, - sentiment: { - positive: 0.55, - negative: 0.0, - neutral: 0.45, - mixed: 0.0, - label: 'neutral', - sentiment: 0.55, - }, - username: 'test', - member: memberCreated.id, - sourceId: '#sourceId2', - } - - const activityCreated1 = await ActivityRepository.create(activity1, mockIRepositoryOptions) - await ActivityRepository.create(activity2, mockIRepositoryOptions) - - // Control - expect( - (await ActivityRepository.findAndCountAll({ filter: {} }, mockIRepositoryOptions)).count, - ).toBe(2) - - // Filter by how positive activities are - const filteredActivities = await ActivityRepository.findAndCountAll( - { filter: { positiveSentimentRange: [0.6, 1] } }, - mockIRepositoryOptions, - ) - - expect(filteredActivities.count).toBe(1) - expect(filteredActivities.rows[0].id).toBe(activityCreated1.id) - - // Filter by whether activities are positive or not - const filteredActivities2 = await ActivityRepository.findAndCountAll( - { filter: { sentimentLabel: 'positive' } }, - mockIRepositoryOptions, - ) - - expect(filteredActivities2.count).toBe(1) - expect(filteredActivities2.rows[0].id).toBe(activityCreated1.id) - - // No filter, but sorting - const filteredActivities3 = await ActivityRepository.findAndCountAll( - { filter: {}, orderBy: 'sentiment.positive_DESC' }, - mockIRepositoryOptions, - ) - expect(filteredActivities3.count).toBe(2) - expect(filteredActivities3.rows[0].sentiment.positive).toBeGreaterThan( - filteredActivities3.rows[1].sentiment.positive, - ) - }) - it('Negative sentiment filter and sort', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - const memberCreated = await MemberRepository.create( - { - username: { - [PlatformType.GITHUB]: 'test', - }, - displayName: 'Member 1', - joinedAt: '2020-05-27T15:13:30Z', - }, - mockIRepositoryOptions, - ) - - const activity1 = { - type: 'activity', - timestamp: '2020-05-27T15:13:30Z', - platform: PlatformType.GITHUB, - sentiment: { - positive: 0.98, - negative: 0.0, - neutral: 0.02, - mixed: 0.0, - label: 'positive', - sentiment: 0.98, - }, - username: 'test', - member: memberCreated.id, - sourceId: '#sourceId1', - } - - const activity2 = { - type: 'activity', - timestamp: '2020-05-27T15:13:30Z', - platform: PlatformType.GITHUB, - sentiment: { - positive: 0.01, - negative: 0.55, - neutral: 0.55, - mixed: 0.0, - label: 'negative', - sentiment: -0.54, - }, - username: 'test', - member: memberCreated.id, - sourceId: '#sourceId2', - } - - await ActivityRepository.create(activity1, mockIRepositoryOptions) - const activityCreated2 = await ActivityRepository.create(activity2, mockIRepositoryOptions) - - // Control - expect( - (await ActivityRepository.findAndCountAll({ filter: {} }, mockIRepositoryOptions)).count, - ).toBe(2) - - // Filter by how positive activities are - const filteredActivities = await ActivityRepository.findAndCountAll( - { filter: { negativeSentimentRange: [0.5, 1] } }, - mockIRepositoryOptions, - ) - - expect(filteredActivities.count).toBe(1) - expect(filteredActivities.rows[0].id).toBe(activityCreated2.id) - - // Filter by whether activities are positive or not - const filteredActivities2 = await ActivityRepository.findAndCountAll( - { filter: { sentimentLabel: 'negative' } }, - mockIRepositoryOptions, - ) - - expect(filteredActivities2.count).toBe(1) - expect(filteredActivities2.rows[0].id).toBe(activityCreated2.id) - - // No filter, but sorting - const filteredActivities3 = await ActivityRepository.findAndCountAll( - { filter: {}, orderBy: 'sentiment.negative_DESC' }, - mockIRepositoryOptions, - ) - expect(filteredActivities3.count).toBe(2) - expect(filteredActivities3.rows[0].sentiment.negative).toBeGreaterThan( - filteredActivities3.rows[1].sentiment.negative, - ) - }) - - it('Overall sentiment filter and sort', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const memberCreated = await MemberRepository.create( - { - username: { - github: 'test', - }, - displayName: 'Member 1', - joinedAt: '2020-05-27T15:13:30Z', - }, - mockIRepositoryOptions, - ) - - const activity1 = { - type: 'activity', - timestamp: '2020-05-27T15:13:30Z', - platform: PlatformType.GITHUB, - sentiment: { - positive: 0.98, - negative: 0.0, - neutral: 0.02, - mixed: 0.0, - label: 'positive', - sentiment: 0.98, - }, - username: 'test', - member: memberCreated.id, - sourceId: '#sourceId1', - } - - const activity2 = { - type: 'activity', - timestamp: '2020-05-27T15:13:30Z', - platform: PlatformType.GITHUB, - sentiment: { - positive: 0.55, - negative: 0.0, - neutral: 0.45, - mixed: 0.0, - label: 'neutral', - sentiment: 0.55, - }, - username: 'test', - member: memberCreated.id, - sourceId: '#sourceId2', - } - - const activityCreated1 = await ActivityRepository.create(activity1, mockIRepositoryOptions) - await ActivityRepository.create(activity2, mockIRepositoryOptions) - - // Control - expect( - (await ActivityRepository.findAndCountAll({ filter: {} }, mockIRepositoryOptions)).count, - ).toBe(2) - - // Filter by how positive activities are - const filteredActivities = await ActivityRepository.findAndCountAll( - { filter: { sentimentRange: [0.6, 1] } }, - mockIRepositoryOptions, - ) - - expect(filteredActivities.count).toBe(1) - expect(filteredActivities.rows[0].id).toBe(activityCreated1.id) - - // No filter, but sorting - const filteredActivities3 = await ActivityRepository.findAndCountAll( - { filter: {}, orderBy: 'sentiment_DESC' }, - mockIRepositoryOptions, - ) - expect(filteredActivities3.count).toBe(2) - expect(filteredActivities3.rows[0].sentiment.positive).toBeGreaterThan( - filteredActivities3.rows[1].sentiment.positive, - ) - }) - - it('Member related attributes filters', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - const mas = new MemberAttributeSettingsService(mockIRepositoryOptions) - - await mas.createPredefined(DEFAULT_MEMBER_ATTRIBUTES) - - const memberAttributeSettings = ( - await MemberAttributeSettingsRepository.findAndCountAll({}, mockIRepositoryOptions) - ).rows - - const memberCreated1 = await MemberRepository.create( - { - username: { - [PlatformType.GITHUB]: 'test', - }, - displayName: 'Anil', - attributes: { - [MemberAttributeName.IS_TEAM_MEMBER]: { - default: true, - [PlatformType.CROWD]: true, - }, - [MemberAttributeName.LOCATION]: { - default: 'Berlin', - [PlatformType.GITHUB]: 'Berlin', - [PlatformType.SLACK]: 'Turkey', - }, - }, - joinedAt: '2020-05-27T15:13:30Z', - }, - mockIRepositoryOptions, - ) - - const memberCreated2 = await MemberRepository.create( - { - username: { - [PlatformType.GITHUB]: 'Michael', - }, - displayName: 'Michael', - attributes: { - [MemberAttributeName.IS_TEAM_MEMBER]: { - default: false, - [PlatformType.CROWD]: false, - }, - [MemberAttributeName.LOCATION]: { - default: 'Scranton', - [PlatformType.GITHUB]: 'Scranton', - [PlatformType.SLACK]: 'New York', - }, - }, - joinedAt: '2020-05-27T15:13:30Z', - }, - mockIRepositoryOptions, - ) - - const activity1 = { - type: 'activity', - timestamp: '2020-05-27T15:13:30Z', - platform: PlatformType.GITHUB, - sentiment: { - positive: 0.98, - negative: 0.0, - neutral: 0.02, - mixed: 0.0, - label: 'positive', - sentiment: 0.98, - }, - username: 'test', - member: memberCreated1.id, - sourceId: '#sourceId1', - } - - const activity2 = { - type: 'activity', - timestamp: '2020-05-27T15:13:30Z', - platform: PlatformType.GITHUB, - sentiment: { - positive: 0.55, - negative: 0.0, - neutral: 0.45, - mixed: 0.0, - label: 'neutral', - sentiment: 0.55, - }, - username: 'Michael', - member: memberCreated2.id, - sourceId: '#sourceId2', - } - - const activityCreated1 = await ActivityRepository.create(activity1, mockIRepositoryOptions) - const activityCreated2 = await ActivityRepository.create(activity2, mockIRepositoryOptions) - - // Control - expect( - (await ActivityRepository.findAndCountAll({ filter: {} }, mockIRepositoryOptions)).count, - ).toBe(2) - - // Filter by member.isTeamMember - let filteredActivities = await ActivityRepository.findAndCountAll( - { - advancedFilter: { - member: { - isTeamMember: { - not: false, - }, - }, - }, - attributesSettings: memberAttributeSettings, - }, - mockIRepositoryOptions, - ) - - expect(filteredActivities.count).toBe(1) - expect(filteredActivities.rows[0].id).toBe(activityCreated1.id) - - filteredActivities = await ActivityRepository.findAndCountAll( - { - advancedFilter: { - member: { - 'attributes.location.slack': 'New York', - }, - }, - attributesSettings: memberAttributeSettings, - }, - mockIRepositoryOptions, - ) - - expect(filteredActivities.count).toBe(1) - expect(filteredActivities.rows[0].id).toBe(activityCreated2.id) - }) - }) -}) diff --git a/backend/src/database/repositories/__tests__/memberEnrichmentCacheRepository.test.ts b/backend/src/database/repositories/__tests__/memberEnrichmentCacheRepository.test.ts deleted file mode 100644 index 8b2438a340..0000000000 --- a/backend/src/database/repositories/__tests__/memberEnrichmentCacheRepository.test.ts +++ /dev/null @@ -1,161 +0,0 @@ -import { randomUUID } from 'crypto' - -import MemberRepository from '../memberRepository' -import SequelizeTestUtils from '../../utils/sequelizeTestUtils' -import { PlatformType } from '@crowd/types' -import MemberEnrichmentCacheRepository from '../memberEnrichmentCacheRepository' -import { generateUUIDv1 } from '@crowd/common' - -const db = null - -describe('MemberEnrichmentCacheRepository tests', () => { - beforeEach(async () => { - await SequelizeTestUtils.wipeDatabase(db) - }) - - afterAll((done) => { - // Closing the DB connection allows Jest to exit successfully. - SequelizeTestUtils.closeConnection(db) - done() - }) - - describe('upsert method', () => { - it('Should create non existing item successfully', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const member2add = { - username: { - [PlatformType.GITHUB]: { - username: 'michael_scott', - }, - }, - displayName: 'Member 1', - email: 'michael@dd.com', - score: 10, - attributes: {}, - joinedAt: '2020-05-27T15:13:30Z', - } - - const member = await MemberRepository.create(member2add, mockIRepositoryOptions) - - const enrichmentData = { - enrichmentField1: 'string', - enrichmentField2: 24, - arrayEnrichmentField: [1, 2, 3], - } - - const cache = await MemberEnrichmentCacheRepository.upsert( - member.id, - enrichmentData, - mockIRepositoryOptions, - ) - - expect(cache.memberId).toEqual(member.id) - expect(cache.data).toStrictEqual(enrichmentData) - }) - - it('Should update the data of existing cache item with incoming data', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const member2add = { - username: { - [PlatformType.GITHUB]: { - username: 'michael_scott', - }, - }, - displayName: 'Member 1', - email: 'michael@dd.com', - score: 10, - attributes: {}, - joinedAt: '2020-05-27T15:13:30Z', - } - - const member = await MemberRepository.create(member2add, mockIRepositoryOptions) - - const enrichmentData = { - enrichmentField1: 'string', - enrichmentField2: 24, - arrayEnrichmentField: [1, 2, 3], - } - - let cache = await MemberEnrichmentCacheRepository.upsert( - member.id, - enrichmentData, - mockIRepositoryOptions, - ) - - const newerEnrichmentData = { - enrichmentField1: 'anotherString', - enrichmentField2: 99, - arrayEnrichmentField: ['a', 'b', 'c'], - } - - // should overwrite with new cache data - cache = await MemberEnrichmentCacheRepository.upsert( - member.id, - newerEnrichmentData, - mockIRepositoryOptions, - ) - - expect(cache.memberId).toEqual(member.id) - expect(cache.data).toStrictEqual(newerEnrichmentData) - - // when we send an empty object, it shouldn't overwrite - cache = await MemberEnrichmentCacheRepository.upsert(member.id, {}, mockIRepositoryOptions) - - expect(cache.memberId).toEqual(member.id) - expect(cache.data).toStrictEqual(newerEnrichmentData) - }) - }) - - describe('findByMemberId method', () => { - it('Should find enrichment cache by memberId', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const member2add = { - username: { - [PlatformType.GITHUB]: { - username: 'michael_scott', - }, - }, - displayName: 'Member 1', - email: 'michael@dd.com', - score: 10, - attributes: {}, - joinedAt: '2020-05-27T15:13:30Z', - } - - const member = await MemberRepository.create(member2add, mockIRepositoryOptions) - - const enrichmentData = { - enrichmentField1: 'string', - enrichmentField2: 24, - arrayEnrichmentField: [1, 2, 3], - } - - await MemberEnrichmentCacheRepository.upsert( - member.id, - enrichmentData, - mockIRepositoryOptions, - ) - - const cache = await MemberEnrichmentCacheRepository.findByMemberId( - member.id, - mockIRepositoryOptions, - ) - - expect(cache.memberId).toEqual(member.id) - expect(cache.data).toEqual(enrichmentData) - }) - - it('Should return null for non-existing cache entry', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const cache = await MemberEnrichmentCacheRepository.findByMemberId( - randomUUID(), - mockIRepositoryOptions, - ) - expect(cache).toBeNull() - }) - }) -}) diff --git a/backend/src/database/repositories/__tests__/memberRepository.test.ts b/backend/src/database/repositories/__tests__/memberRepository.test.ts deleted file mode 100644 index 13945324b8..0000000000 --- a/backend/src/database/repositories/__tests__/memberRepository.test.ts +++ /dev/null @@ -1,3959 +0,0 @@ -import { v4 as uuid } from 'uuid' -import moment from 'moment' - -import { Error404 } from '@crowd/common' -import { PlatformType, SegmentStatus } from '@crowd/types' -import { generateUUIDv1 } from '@crowd/common' -import SequelizeTestUtils from '../../utils/sequelizeTestUtils' -import MemberRepository from '../memberRepository' -import NoteRepository from '../noteRepository' -import OrganizationRepository from '../organizationRepository' -import TagRepository from '../tagRepository' -import TaskRepository from '../taskRepository' -import lodash from 'lodash' -import SegmentRepository from '../segmentRepository' -import { populateSegments } from '../../utils/segmentTestUtils' -import MemberService from '../../../services/memberService' -import OrganizationService from '../../../services/organizationService' - -const db = null - -function mapUsername(data: any): any { - const username = {} - Object.keys(data).forEach((platform) => { - const usernameData = data[platform] - - if (Array.isArray(usernameData)) { - username[platform] = [] - if (usernameData.length > 0) { - for (const entry of usernameData) { - if (typeof entry === 'string') { - username[platform].push(entry) - } else if (typeof entry === 'object') { - username[platform].push((entry as any).username) - } else { - throw new Error('Invalid username type') - } - } - } - } else if (typeof usernameData === 'object') { - username[platform] = [usernameData.username] - } else if (typeof usernameData === 'string') { - username[platform] = [usernameData] - } else { - throw new Error('Invalid username type') - } - }) - return username -} - -describe('MemberRepository tests', () => { - beforeEach(async () => { - await SequelizeTestUtils.wipeDatabase(db) - }) - - afterAll((done) => { - // Closing the DB connection allows Jest to exit successfully. - SequelizeTestUtils.closeConnection(db) - done() - }) - - describe('create method', () => { - it('Should create the given member succesfully', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const member2add = { - username: { - [PlatformType.GITHUB]: { - username: 'anil_github', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 1', - emails: ['lala@l.com'], - score: 10, - attributes: { - [PlatformType.GITHUB]: { - name: 'Quoc-Anh Nguyen', - isHireable: true, - url: 'https://github.com/imcvampire', - websiteUrl: 'https://imcvampire.js.org/', - bio: 'Lazy geek', - location: 'Helsinki, Finland', - actions: [ - { - score: 2, - timestamp: '2021-05-27T15:13:30Z', - }, - ], - }, - [PlatformType.TWITTER]: { - profile_url: 'https://twitter.com/imcvampire', - url: 'https://twitter.com/imcvampire', - }, - }, - joinedAt: '2020-05-27T15:13:30Z', - } - - const cloned = lodash.cloneDeep(member2add) - const memberCreated = await MemberRepository.create(cloned, mockIRepositoryOptions) - - // Trim the hour part from timestamp so we can atleast test if the day is correct for createdAt and joinedAt - memberCreated.createdAt = memberCreated.createdAt.toISOString().split('T')[0] - memberCreated.updatedAt = memberCreated.updatedAt.toISOString().split('T')[0] - - const expectedMemberCreated = { - id: memberCreated.id, - username: mapUsername(member2add.username), - attributes: member2add.attributes, - displayName: member2add.displayName, - emails: member2add.emails, - score: member2add.score, - identities: ['github'], - lastEnriched: null, - enrichedBy: [], - contributions: null, - organizations: [], - notes: [], - tasks: [], - importHash: null, - createdAt: SequelizeTestUtils.getNowWithoutTime(), - updatedAt: SequelizeTestUtils.getNowWithoutTime(), - deletedAt: null, - tenantId: mockIRepositoryOptions.currentTenant.id, - segments: mockIRepositoryOptions.currentSegments, - createdById: mockIRepositoryOptions.currentUser.id, - updatedById: mockIRepositoryOptions.currentUser.id, - activeOn: [], - activityTypes: [], - reach: { total: -1 }, - joinedAt: new Date('2020-05-27T15:13:30Z'), - tags: [], - noMerge: [], - toMerge: [], - activityCount: 0, - activeDaysCount: 0, - lastActive: null, - averageSentiment: 0, - numberOfOpenSourceContributions: 0, - lastActivity: null, - affiliations: [], - manuallyCreated: false, - } - expect(memberCreated).toStrictEqual(expectedMemberCreated) - }) - - it('Should create succesfully but return without relations when doPopulateRelations=false', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const member2add = { - username: { - [PlatformType.GITHUB]: { - username: 'anil_github', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 1', - emails: ['lala@l.com'], - score: 10, - attributes: { - [PlatformType.GITHUB]: { - name: 'Quoc-Anh Nguyen', - isHireable: true, - url: 'https://github.com/imcvampire', - websiteUrl: 'https://imcvampire.js.org/', - bio: 'Lazy geek', - location: 'Helsinki, Finland', - actions: [ - { - score: 2, - timestamp: '2021-05-27T15:13:30Z', - }, - ], - }, - [PlatformType.TWITTER]: { - profile_url: 'https://twitter.com/imcvampire', - url: 'https://twitter.com/imcvampire', - }, - }, - joinedAt: '2020-05-27T15:13:30Z', - } - - const cloned = lodash.cloneDeep(member2add) - const memberCreated = await MemberRepository.create(cloned, mockIRepositoryOptions, false) - - // Trim the hour part from timestamp so we can atleast test if the day is correct for createdAt and joinedAt - memberCreated.createdAt = memberCreated.createdAt.toISOString().split('T')[0] - memberCreated.updatedAt = memberCreated.updatedAt.toISOString().split('T')[0] - - const expectedMemberCreated = { - id: memberCreated.id, - username: mapUsername(member2add.username), - displayName: member2add.displayName, - attributes: member2add.attributes, - emails: member2add.emails, - lastEnriched: null, - enrichedBy: [], - contributions: null, - score: member2add.score, - importHash: null, - createdAt: SequelizeTestUtils.getNowWithoutTime(), - updatedAt: SequelizeTestUtils.getNowWithoutTime(), - deletedAt: null, - tenantId: mockIRepositoryOptions.currentTenant.id, - segments: mockIRepositoryOptions.currentSegments, - createdById: mockIRepositoryOptions.currentUser.id, - updatedById: mockIRepositoryOptions.currentUser.id, - reach: { total: -1 }, - organizations: [], - joinedAt: new Date('2020-05-27T15:13:30Z'), - affiliations: [], - manuallyCreated: false, - } - expect(memberCreated).toStrictEqual(expectedMemberCreated) - }) - - it('Should succesfully create member with only mandatory username and joinedAt fields', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const member2add = { - username: { - [PlatformType.GITHUB]: { - username: 'anil', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 1', - joinedAt: '2020-05-27T15:13:30Z', - } - - const cloned = lodash.cloneDeep(member2add) - const memberCreated = await MemberRepository.create(cloned, mockIRepositoryOptions) - - // Trim the hour part from timestamp so we can atleast test if the day is correct for createdAt and joinedAt - memberCreated.createdAt = memberCreated.createdAt.toISOString().split('T')[0] - memberCreated.updatedAt = memberCreated.updatedAt.toISOString().split('T')[0] - - const expectedMemberCreated = { - id: memberCreated.id, - username: mapUsername(member2add.username), - displayName: member2add.displayName, - organizations: [], - attributes: {}, - identities: ['github'], - emails: [], - lastEnriched: null, - enrichedBy: [], - contributions: null, - score: -1, - importHash: null, - createdAt: SequelizeTestUtils.getNowWithoutTime(), - updatedAt: SequelizeTestUtils.getNowWithoutTime(), - deletedAt: null, - tenantId: mockIRepositoryOptions.currentTenant.id, - segments: mockIRepositoryOptions.currentSegments, - createdById: mockIRepositoryOptions.currentUser.id, - updatedById: mockIRepositoryOptions.currentUser.id, - activeOn: [], - activityTypes: [], - reach: { total: -1 }, - joinedAt: new Date('2020-05-27T15:13:30Z'), - notes: [], - tasks: [], - tags: [], - noMerge: [], - toMerge: [], - activityCount: 0, - activeDaysCount: 0, - averageSentiment: 0, - numberOfOpenSourceContributions: 0, - lastActive: null, - lastActivity: null, - affiliations: [], - manuallyCreated: false, - } - - expect(memberCreated).toStrictEqual(expectedMemberCreated) - }) - - it('Should throw error when no username given', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - // no username field, should reject the promise with - // sequelize unique constraint - const member2add = { - joinedAt: '2020-05-27T15:13:30Z', - emails: ['test@crowd.dev'], - } - - await expect(() => - MemberRepository.create(member2add, mockIRepositoryOptions), - ).rejects.toThrow() - }) - - it('Should throw error when no joinedAt given', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - // no username field, should reject the promise with - // sequelize unique constraint - const member2add = { - username: { - [PlatformType.GITHUB]: { - username: 'anil', - integrationId: generateUUIDv1(), - }, - }, - emails: ['test@crowd.dev'], - } - - await expect(() => - MemberRepository.create(member2add, mockIRepositoryOptions), - ).rejects.toThrow() - }) - - it('Should succesfully create member with notes', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const notes1 = await NoteRepository.create( - { - body: 'note1', - }, - mockIRepositoryOptions, - ) - - const notes2 = await NoteRepository.create( - { - body: 'note2', - }, - mockIRepositoryOptions, - ) - - const member2add = { - username: { - [PlatformType.SLACK]: { - username: 'anil', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 1', - joinedAt: '2020-05-27T15:13:30Z', - notes: [notes1.id, notes2.id], - } - - const memberCreated = await MemberRepository.create(member2add, mockIRepositoryOptions) - expect(memberCreated.notes).toHaveLength(2) - expect(memberCreated.notes[0].id).toEqual(notes1.id) - expect(memberCreated.notes[1].id).toEqual(notes2.id) - }) - - it('Should succesfully create member with tasks', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const tasks1 = await TaskRepository.create( - { - name: 'task1', - }, - mockIRepositoryOptions, - ) - - const task2 = await TaskRepository.create( - { - name: 'task2', - }, - mockIRepositoryOptions, - ) - - const member2add = { - username: { - [PlatformType.DISCORD]: { - username: 'anil', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 1', - joinedAt: '2020-05-27T15:13:30Z', - tasks: [tasks1.id, task2.id], - } - - const memberCreated = await MemberRepository.create(member2add, mockIRepositoryOptions) - expect(memberCreated.tasks).toHaveLength(2) - expect(memberCreated.tasks.find((t) => t.id === tasks1.id)).not.toBeUndefined() - expect(memberCreated.tasks.find((t) => t.id === task2.id)).not.toBeUndefined() - }) - - it('Should succesfully create member with organization affiliations', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - const segmentRepo = new SegmentRepository(mockIRepositoryOptions) - - const segment1 = await segmentRepo.create({ - name: 'Crowd.dev - Segment1', - url: '', - parentName: 'Crowd.dev - Segment1', - grandparentName: 'Crowd.dev - Segment1', - slug: 'crowd.dev-1', - parentSlug: 'crowd.dev-1', - grandparentSlug: 'crowd.dev-1', - status: SegmentStatus.ACTIVE, - sourceId: null, - sourceParentId: null, - }) - - const segment2 = await segmentRepo.create({ - name: 'Crowd.dev - Segment2', - url: '', - parentName: 'Crowd.dev - Segment2', - grandparentName: 'Crowd.dev - Segment2', - slug: 'crowd.dev-2', - parentSlug: 'crowd.dev-2', - grandparentSlug: 'crowd.dev-2', - status: SegmentStatus.ACTIVE, - sourceId: null, - sourceParentId: null, - }) - - const org1 = await OrganizationRepository.create( - { - displayName: 'crowd.dev', - }, - mockIRepositoryOptions, - ) - - const member2add = { - username: { - [PlatformType.DISCORD]: { - username: 'anil', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 1', - joinedAt: '2020-05-27T15:13:30Z', - affiliations: [ - { - segmentId: segment1.id, - organizationId: org1.id, - }, - { - segmentId: segment2.id, - organizationId: null, - }, - ], - } - - const memberCreated = await MemberRepository.create(member2add, mockIRepositoryOptions) - expect(memberCreated.affiliations).toHaveLength(2) - expect( - memberCreated.affiliations.filter((a) => a.segmentId === segment1.id)[0].organizationId, - ).toEqual(org1.id) - expect( - memberCreated.affiliations.filter((a) => a.segmentId === segment2.id)[0].organizationId, - ).toBeNull() - }) - }) - - describe('findById method', () => { - it('Should successfully find created member by id', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const member2add = { - username: { - [PlatformType.GITHUB]: { - username: 'anil', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 1', - joinedAt: '2020-05-27T15:13:30Z', - } - - const cloned = lodash.cloneDeep(member2add) - const memberCreated = await MemberRepository.create(cloned, mockIRepositoryOptions) - - const expectedMemberFound = { - id: memberCreated.id, - username: mapUsername(member2add.username), - displayName: member2add.displayName, - identities: ['github'], - attributes: {}, - emails: [], - lastEnriched: null, - enrichedBy: [], - contributions: null, - score: -1, - importHash: null, - organizations: [], - createdAt: SequelizeTestUtils.getNowWithoutTime(), - updatedAt: SequelizeTestUtils.getNowWithoutTime(), - deletedAt: null, - tenantId: mockIRepositoryOptions.currentTenant.id, - segments: mockIRepositoryOptions.currentSegments, - createdById: mockIRepositoryOptions.currentUser.id, - updatedById: mockIRepositoryOptions.currentUser.id, - activeOn: [], - activityTypes: [], - reach: { total: -1 }, - notes: [], - tasks: [], - joinedAt: new Date('2020-05-27T15:13:30Z'), - tags: [], - noMerge: [], - toMerge: [], - activityCount: 0, - activeDaysCount: 0, - averageSentiment: 0, - numberOfOpenSourceContributions: 0, - lastActive: null, - lastActivity: null, - affiliations: [], - manuallyCreated: false, - } - - const memberById = await MemberRepository.findById(memberCreated.id, mockIRepositoryOptions) - - // Trim the hour part from timestamp so we can atleast test if the day is correct for createdAt and joinedAt - memberById.createdAt = memberById.createdAt.toISOString().split('T')[0] - memberById.updatedAt = memberById.updatedAt.toISOString().split('T')[0] - - expect(memberById).toStrictEqual(expectedMemberFound) - }) - - it('Should return a plain object when called with doPopulateRelations false', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const member2add = { - username: { - [PlatformType.GITHUB]: { - username: 'anil', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 1', - joinedAt: '2020-05-27T15:13:30Z', - } - - const cloned = lodash.cloneDeep(member2add) - const memberCreated = await MemberRepository.create(cloned, mockIRepositoryOptions) - - const expectedMemberFound = { - id: memberCreated.id, - username: mapUsername(member2add.username), - displayName: member2add.displayName, - lastEnriched: null, - enrichedBy: [], - contributions: null, - attributes: {}, - emails: [], - score: -1, - importHash: null, - createdAt: SequelizeTestUtils.getNowWithoutTime(), - updatedAt: SequelizeTestUtils.getNowWithoutTime(), - deletedAt: null, - tenantId: mockIRepositoryOptions.currentTenant.id, - segments: mockIRepositoryOptions.currentSegments, - createdById: mockIRepositoryOptions.currentUser.id, - updatedById: mockIRepositoryOptions.currentUser.id, - reach: { total: -1 }, - organizations: [], - joinedAt: new Date('2020-05-27T15:13:30Z'), - affiliations: [], - manuallyCreated: false, - } - - const memberById = await MemberRepository.findById( - memberCreated.id, - mockIRepositoryOptions, - true, - false, - ) - - // Trim the hour part from timestamp so we can atleast test if the day is correct for createdAt and joinedAt - memberById.createdAt = memberById.createdAt.toISOString().split('T')[0] - memberById.updatedAt = memberById.updatedAt.toISOString().split('T')[0] - - expect(memberById).toStrictEqual(expectedMemberFound) - }) - - it('Should throw 404 error when no member found with given id', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - const { randomUUID } = require('crypto') - - await expect(() => - MemberRepository.findById(randomUUID(), mockIRepositoryOptions), - ).rejects.toThrowError(new Error404()) - }) - }) - - describe('filterIdsInTenant method', () => { - it('Should return the given ids of previously created member entities', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - const member1 = { - username: { - [PlatformType.GITHUB]: { - username: 'test1', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 1', - joinedAt: '2020-05-27T15:13:30Z', - } - const member2 = { - username: { - [PlatformType.GITHUB]: { - username: 'test2', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'some-other-name', - joinedAt: '2020-05-28T15:13:30Z', - } - - const member1Returned = await MemberRepository.create(member1, mockIRepositoryOptions) - const member2Returned = await MemberRepository.create(member2, mockIRepositoryOptions) - - const filterIdsReturned = await MemberRepository.filterIdsInTenant( - [member1Returned.id, member2Returned.id], - mockIRepositoryOptions, - ) - - expect(filterIdsReturned).toStrictEqual([member1Returned.id, member2Returned.id]) - }) - - it('Should only return the ids of previously created members and filter random uuids out', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const member1 = { - username: { - [PlatformType.GITHUB]: { - username: 'test3', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 1', - joinedAt: '2020-05-29T15:14:30Z', - } - - const member1Returned = await MemberRepository.create(member1, mockIRepositoryOptions) - - const { randomUUID } = require('crypto') - - const filterIdsReturned = await MemberRepository.filterIdsInTenant( - [member1Returned.id, randomUUID(), randomUUID()], - mockIRepositoryOptions, - ) - - expect(filterIdsReturned).toStrictEqual([member1Returned.id]) - }) - - it('Should return an empty array for an irrelevant tenant', async () => { - let mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const member1 = { - username: { - [PlatformType.GITHUB]: { - username: 'test3', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 1', - joinedAt: '2020-04-29T15:14:30Z', - } - - const member1Returned = await MemberRepository.create(member1, mockIRepositoryOptions) - - // create a new tenant and bind options to it - mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const filterIdsReturned = await MemberRepository.filterIdsInTenant( - [member1Returned.id], - mockIRepositoryOptions, - ) - - expect(filterIdsReturned).toStrictEqual([]) - }) - }) - - describe('memberExists method', () => { - it('Should return the created member for a simple query', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - const member1 = { - username: { - [PlatformType.TWITTER]: { - username: 'test1', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 1', - joinedAt: '2020-05-27T15:13:30Z', - emails: ['joan@crowd.dev'], - } - const member1Returned = await MemberRepository.create(member1, mockIRepositoryOptions) - - const found = await MemberRepository.memberExists( - 'test1', - PlatformType.TWITTER, - mockIRepositoryOptions, - ) - - expect(found).toStrictEqual(member1Returned) - }) - - it('Should a plain object when called with doPopulateRelations false', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - const member1 = { - username: { - [PlatformType.TWITTER]: { - username: 'test1', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 1', - joinedAt: '2020-05-27T15:13:30Z', - emails: ['joan@crowd.dev'], - } - const member1Returned = await MemberRepository.create(member1, mockIRepositoryOptions) - delete member1Returned.toMerge - delete member1Returned.noMerge - delete member1Returned.tags - delete member1Returned.activities - delete member1Returned.notes - delete member1Returned.tasks - delete member1Returned.lastActive - delete member1Returned.activityCount - delete member1Returned.averageSentiment - delete member1Returned.lastActivity - delete member1Returned.activeOn - delete member1Returned.identities - delete member1Returned.activityTypes - delete member1Returned.activeDaysCount - delete member1Returned.numberOfOpenSourceContributions - delete member1Returned.affiliations - delete member1Returned.manuallyCreated - member1Returned.segments = member1Returned.segments.map((s) => s.id) - - const found = await MemberRepository.memberExists( - 'test1', - PlatformType.TWITTER, - mockIRepositoryOptions, - false, - ) - - expect(found).toStrictEqual(member1Returned) - }) - - it('Should return null when non-existent at platform level', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const member1 = { - username: { - [PlatformType.TWITTER]: { - username: 'test1', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 1', - joinedAt: '2020-05-27T15:13:30Z', - emails: ['joan@crowd.dev'], - } - await MemberRepository.create(member1, mockIRepositoryOptions) - - await expect(() => - MemberRepository.memberExists('test1', PlatformType.GITHUB, mockIRepositoryOptions), - ) - }) - - it('Should return null when non-existent at username level', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const member1 = { - username: { - [PlatformType.TWITTER]: { - username: 'test1', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 1', - joinedAt: '2020-05-27T15:13:30Z', - emails: ['joan@crowd.dev'], - } - await MemberRepository.create(member1, mockIRepositoryOptions) - - const memberExists = await MemberRepository.memberExists( - 'test2', - PlatformType.TWITTER, - mockIRepositoryOptions, - ) - - expect(memberExists).toBeNull() - }) - }) - - describe('findAndCountAll method', () => { - it('is successfully finding and counting all members, sortedBy activitiesCount DESC', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const member1 = await MemberRepository.create( - { - username: { - [PlatformType.SLACK]: { - username: 'test1', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 1', - score: '1', - joinedAt: new Date(), - }, - mockIRepositoryOptions, - ) - const member2 = await MemberRepository.create( - { - username: { - [PlatformType.SLACK]: { - username: 'test2', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 2', - score: '6', - joinedAt: new Date(), - }, - mockIRepositoryOptions, - ) - const member3 = await MemberRepository.create( - { - username: { - [PlatformType.SLACK]: { - username: 'test3', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 3', - score: '7', - joinedAt: new Date(), - }, - mockIRepositoryOptions, - ) - - await mockIRepositoryOptions.database.activity.bulkCreate([ - { - type: 'message', - platform: PlatformType.SLACK, - timestamp: new Date(), - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - memberId: member1.id, - username: member1.username[PlatformType.SLACK], - sourceId: '#sourceId1', - }, - { - type: 'message', - platform: PlatformType.SLACK, - timestamp: new Date(), - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - memberId: member2.id, - username: member2.username[PlatformType.SLACK], - sourceId: '#sourceId2', - }, - { - type: 'message', - platform: PlatformType.SLACK, - timestamp: new Date(), - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - memberId: member2.id, - username: member2.username[PlatformType.SLACK], - sourceId: '#sourceId3', - }, - { - type: 'message', - platform: PlatformType.SLACK, - timestamp: new Date(), - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - memberId: member3.id, - username: member3.username[PlatformType.SLACK], - sourceId: '#sourceId4', - }, - { - type: 'message', - platform: PlatformType.SLACK, - timestamp: new Date(), - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - memberId: member3.id, - username: member3.username[PlatformType.SLACK], - sourceId: '#sourceId5', - }, - { - type: 'message', - platform: PlatformType.SLACK, - timestamp: new Date(), - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - memberId: member3.id, - username: member3.username[PlatformType.SLACK], - sourceId: '#sourceId6', - }, - ]) - - await SequelizeTestUtils.refreshMaterializedViews(db) - - const members = await MemberRepository.findAndCountAll( - { filter: {}, orderBy: 'activityCount_DESC' }, - mockIRepositoryOptions, - ) - - expect(members.rows.length).toEqual(3) - expect(members.rows[0].activityCount).toEqual('3') - expect(members.rows[1].activityCount).toEqual('2') - expect(members.rows[2].activityCount).toEqual('1') - }) - - it('is successfully finding and counting all members, sortedBy numberOfOpenSourceContributions DESC', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - await MemberRepository.create( - { - username: { [PlatformType.TWITTER]: 'test1' }, - displayName: 'Member 1', - score: '1', - joinedAt: new Date(), - contributions: [ - { - id: 112529472, - url: 'https://github.com/bachman/pied-piper', - topics: ['compression', 'data', 'middle-out', 'Java'], - summary: 'Pied Piper: 10 commits in 1 day', - numberCommits: 10, - lastCommitDate: '2023-03-10', - firstCommitDate: '2023-03-01', - }, - { - id: 112529473, - url: 'https://github.com/bachman/aviato', - topics: ['Python', 'Django'], - summary: 'Aviato: 5 commits in 1 day', - numberCommits: 5, - lastCommitDate: '2023-02-25', - firstCommitDate: '2023-02-20', - }, - { - id: 112529476, - url: 'https://github.com/bachman/erlichbot', - topics: ['Python', 'Slack API'], - summary: 'ErlichBot: 2 commits in 1 day', - numberCommits: 2, - lastCommitDate: '2023-01-25', - firstCommitDate: '2023-01-24', - }, - ], - }, - mockIRepositoryOptions, - ) - await MemberRepository.create( - { - username: { [PlatformType.TWITTER]: 'test2' }, - displayName: 'Member 2', - score: '6', - joinedAt: new Date(), - contributions: [ - { - id: 112529473, - url: 'https://github.com/bighead/silicon-valley', - topics: ['TV Shows', 'Comedy', 'Startups'], - summary: 'Silicon Valley: 50 commits in 2 weeks', - numberCommits: 50, - lastCommitDate: '02/01/2023', - firstCommitDate: '01/17/2023', - }, - { - id: 112529474, - url: 'https://github.com/bighead/startup-ideas', - topics: ['Ideas', 'Startups'], - summary: 'Startup Ideas: 20 commits in 1 week', - numberCommits: 20, - lastCommitDate: '03/01/2023', - firstCommitDate: '02/22/2023', - }, - ], - }, - mockIRepositoryOptions, - ) - await MemberRepository.create( - { - username: { [PlatformType.TWITTER]: 'test3' }, - displayName: 'Member 3', - score: '7', - joinedAt: new Date(), - }, - mockIRepositoryOptions, - ) - - await SequelizeTestUtils.refreshMaterializedViews(db) - - const members = await MemberRepository.findAndCountAll( - { filter: {}, orderBy: 'numberOfOpenSourceContributions_DESC' }, - mockIRepositoryOptions, - ) - - expect(members.rows.length).toEqual(3) - expect(members.rows[0].numberOfOpenSourceContributions).toEqual(3) - expect(members.rows[1].numberOfOpenSourceContributions).toEqual(2) - expect(members.rows[2].numberOfOpenSourceContributions).toEqual(0) - }) - - it('is successfully finding and counting all members, numberOfOpenSourceContributions range gte than 3 and less or equal to 6', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - await MemberRepository.create( - { - username: { [PlatformType.TWITTER]: 'test1' }, - displayName: 'Member 1', - score: '1', - joinedAt: new Date(), - contributions: [ - { - id: 112529472, - url: 'https://github.com/bachman/pied-piper', - topics: ['compression', 'data', 'middle-out', 'Java'], - summary: 'Pied Piper: 10 commits in 1 day', - numberCommits: 10, - lastCommitDate: '2023-03-10', - firstCommitDate: '2023-03-01', - }, - { - id: 112529473, - url: 'https://github.com/bachman/aviato', - topics: ['Python', 'Django'], - summary: 'Aviato: 5 commits in 1 day', - numberCommits: 5, - lastCommitDate: '2023-02-25', - firstCommitDate: '2023-02-20', - }, - { - id: 112529476, - url: 'https://github.com/bachman/erlichbot', - topics: ['Python', 'Slack API'], - summary: 'ErlichBot: 2 commits in 1 day', - numberCommits: 2, - lastCommitDate: '2023-01-25', - firstCommitDate: '2023-01-24', - }, - { - id: 112529473, - url: 'https://github.com/bighead/silicon-valley', - topics: ['TV Shows', 'Comedy', 'Startups'], - summary: 'Silicon Valley: 50 commits in 2 weeks', - numberCommits: 50, - lastCommitDate: '02/01/2023', - firstCommitDate: '01/17/2023', - }, - ], - }, - mockIRepositoryOptions, - ) - await MemberRepository.create( - { - username: { [PlatformType.TWITTER]: 'test2' }, - displayName: 'Member 2', - score: '6', - joinedAt: new Date(), - contributions: [ - { - id: 112529473, - url: 'https://github.com/bighead/silicon-valley', - topics: ['TV Shows', 'Comedy', 'Startups'], - summary: 'Silicon Valley: 50 commits in 2 weeks', - numberCommits: 50, - lastCommitDate: '02/01/2023', - firstCommitDate: '01/17/2023', - }, - { - id: 112529474, - url: 'https://github.com/bighead/startup-ideas', - topics: ['Ideas', 'Startups'], - summary: 'Startup Ideas: 20 commits in 1 week', - numberCommits: 20, - lastCommitDate: '03/01/2023', - firstCommitDate: '02/22/2023', - }, - ], - }, - mockIRepositoryOptions, - ) - await MemberRepository.create( - { - username: { [PlatformType.TWITTER]: 'test3' }, - displayName: 'Member 3', - score: '7', - joinedAt: new Date(), - }, - mockIRepositoryOptions, - ) - - await SequelizeTestUtils.refreshMaterializedViews(db) - - const members = await MemberRepository.findAndCountAll( - { filter: { numberOfOpenSourceContributionsRange: [3, 6] } }, - mockIRepositoryOptions, - ) - - expect(members.rows.length).toEqual(1) - expect(members.rows[0].numberOfOpenSourceContributions).toEqual(4) - }) - - it('is successfully finding and counting all members, numberOfOpenSourceContributions range gte 2', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - await MemberRepository.create( - { - username: { [PlatformType.TWITTER]: 'test1' }, - displayName: 'Member 1', - score: '1', - joinedAt: new Date(), - contributions: [ - { - id: 112529472, - url: 'https://github.com/bachman/pied-piper', - topics: ['compression', 'data', 'middle-out', 'Java'], - summary: 'Pied Piper: 10 commits in 1 day', - numberCommits: 10, - lastCommitDate: '2023-03-10', - firstCommitDate: '2023-03-01', - }, - { - id: 112529473, - url: 'https://github.com/bachman/aviato', - topics: ['Python', 'Django'], - summary: 'Aviato: 5 commits in 1 day', - numberCommits: 5, - lastCommitDate: '2023-02-25', - firstCommitDate: '2023-02-20', - }, - { - id: 112529476, - url: 'https://github.com/bachman/erlichbot', - topics: ['Python', 'Slack API'], - summary: 'ErlichBot: 2 commits in 1 day', - numberCommits: 2, - lastCommitDate: '2023-01-25', - firstCommitDate: '2023-01-24', - }, - { - id: 112529473, - url: 'https://github.com/bighead/silicon-valley', - topics: ['TV Shows', 'Comedy', 'Startups'], - summary: 'Silicon Valley: 50 commits in 2 weeks', - numberCommits: 50, - lastCommitDate: '02/01/2023', - firstCommitDate: '01/17/2023', - }, - ], - }, - mockIRepositoryOptions, - ) - await MemberRepository.create( - { - username: { [PlatformType.TWITTER]: 'test2' }, - displayName: 'Member 2', - score: '6', - joinedAt: new Date(), - contributions: [ - { - id: 112529473, - url: 'https://github.com/bighead/silicon-valley', - topics: ['TV Shows', 'Comedy', 'Startups'], - summary: 'Silicon Valley: 50 commits in 2 weeks', - numberCommits: 50, - lastCommitDate: '02/01/2023', - firstCommitDate: '01/17/2023', - }, - { - id: 112529474, - url: 'https://github.com/bighead/startup-ideas', - topics: ['Ideas', 'Startups'], - summary: 'Startup Ideas: 20 commits in 1 week', - numberCommits: 20, - lastCommitDate: '03/01/2023', - firstCommitDate: '02/22/2023', - }, - ], - }, - mockIRepositoryOptions, - ) - await MemberRepository.create( - { - username: { [PlatformType.TWITTER]: 'test3' }, - displayName: 'Member 3', - score: '7', - joinedAt: new Date(), - }, - mockIRepositoryOptions, - ) - - await SequelizeTestUtils.refreshMaterializedViews(db) - - const members = await MemberRepository.findAndCountAll( - { - filter: { numberOfOpenSourceContributionsRange: [2] }, - orderBy: 'numberOfOpenSourceContributions_DESC', - }, - mockIRepositoryOptions, - ) - - expect(members.rows.length).toEqual(2) - expect(members.rows[0].numberOfOpenSourceContributions).toEqual(4) - expect(members.rows[1].numberOfOpenSourceContributions).toEqual(2) - }) - - it('is successfully finding and counting all members, and tags [nodejs, vuejs]', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const nodeTag = await mockIRepositoryOptions.database.tag.create({ - name: 'nodejs', - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - }) - const vueTag = await mockIRepositoryOptions.database.tag.create({ - name: 'vuejs', - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - }) - - await MemberRepository.create( - { - username: { - [PlatformType.TWITTER]: { - username: 'test1', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 1', - score: '1', - joinedAt: new Date(), - }, - mockIRepositoryOptions, - ) - await MemberRepository.create( - { - username: { - [PlatformType.TWITTER]: { - username: 'test2', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 2', - score: '6', - joinedAt: new Date(), - tags: [nodeTag.id, vueTag.id], - }, - mockIRepositoryOptions, - ) - await MemberRepository.create( - { - username: { - [PlatformType.GITHUB]: { - username: 'test3', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 3', - score: '7', - joinedAt: new Date(), - }, - mockIRepositoryOptions, - ) - - await SequelizeTestUtils.refreshMaterializedViews(db) - - const members = await MemberRepository.findAndCountAll( - { filter: { tags: [nodeTag.id, vueTag.id] } }, - mockIRepositoryOptions, - ) - const member2 = members.rows.find((m) => m.username[PlatformType.TWITTER][0] === 'test2') - expect(members.rows.length).toEqual(1) - expect(member2.tags[0].name).toEqual('nodejs') - expect(member2.tags[1].name).toEqual('vuejs') - }) - - it('is successfully finding and counting all members, and tags [nodejs]', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const nodeTag = await mockIRepositoryOptions.database.tag.create({ - name: 'nodejs', - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - }) - const vueTag = await mockIRepositoryOptions.database.tag.create({ - name: 'vuejs', - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - }) - - await MemberRepository.create( - { - username: { - [PlatformType.GITHUB]: { - username: 'test1', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 1', - score: '1', - joinedAt: new Date(), - tags: [nodeTag.id], - }, - mockIRepositoryOptions, - ) - await MemberRepository.create( - { - username: { - [PlatformType.GITHUB]: { - username: 'test2', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 2', - score: '6', - joinedAt: new Date(), - tags: [nodeTag.id, vueTag.id], - }, - mockIRepositoryOptions, - ) - await MemberRepository.create( - { - username: { - [PlatformType.GITHUB]: { - username: 'test3', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 3', - score: '7', - joinedAt: new Date(), - }, - mockIRepositoryOptions, - ) - - await SequelizeTestUtils.refreshMaterializedViews(db) - - const members = await MemberRepository.findAndCountAll( - { filter: { tags: [nodeTag.id] } }, - mockIRepositoryOptions, - ) - const member1 = members.rows.find((m) => m.username[PlatformType.GITHUB][0] === 'test1') - const member2 = members.rows.find((m) => m.username[PlatformType.GITHUB][0] === 'test2') - - expect(members.rows.length).toEqual(2) - expect(member1.tags[0].name).toEqual('nodejs') - expect(member1.tags[0].name).toEqual('nodejs') - expect(member2.tags[1].name).toEqual('vuejs') - }) - - it('is successfully finding and counting all members, and organisations [crowd.dev, pied piper]', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const crowd = await mockIRepositoryOptions.database.organization.create({ - displayName: 'crowd.dev', - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - }) - await OrganizationRepository.addIdentity( - crowd.id, - { - name: 'crowd.dev', - url: 'https://crowd.dev', - platform: 'crowd', - }, - mockIRepositoryOptions, - ) - - const pp = await mockIRepositoryOptions.database.organization.create({ - displayName: 'pied piper', - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - }) - - await OrganizationRepository.addIdentity( - pp.id, - { - name: 'pied piper', - url: 'https://piedpiper.com', - platform: 'crowd', - }, - mockIRepositoryOptions, - ) - - await MemberRepository.create( - { - username: { - [PlatformType.SLACK]: { - username: 'test1', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 1', - score: '1', - joinedAt: new Date(), - }, - mockIRepositoryOptions, - ) - await MemberRepository.create( - { - username: { - [PlatformType.SLACK]: { - username: 'test2', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 2', - score: '6', - joinedAt: new Date(), - organizations: [crowd.id, pp.id], - }, - mockIRepositoryOptions, - ) - await MemberRepository.create( - { - username: { - [PlatformType.SLACK]: { - username: 'test3', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 3', - score: '7', - joinedAt: new Date(), - }, - mockIRepositoryOptions, - ) - - await SequelizeTestUtils.refreshMaterializedViews(db) - - const members = await MemberRepository.findAndCountAll( - { filter: { organizations: [crowd.id, pp.id] } }, - mockIRepositoryOptions, - ) - const member2 = members.rows.find((m) => m.username[PlatformType.SLACK][0] === 'test2') - expect(members.rows.length).toEqual(1) - expect(member2.organizations[0].displayName).toEqual('crowd.dev') - expect(member2.organizations[1].displayName).toEqual('pied piper') - }) - - it('is successfully finding and counting all members, and scoreRange is gte than 1 and less or equal to 6', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const user1 = { - username: { - [PlatformType.SLACK]: { - username: 'test1', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 1', - score: '1', - joinedAt: new Date(), - } - const user2 = { - username: { - [PlatformType.SLACK]: { - username: 'test2', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 2', - score: '6', - joinedAt: new Date(), - } - const user3 = { - username: { - [PlatformType.SLACK]: { - username: 'test3', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 1', - score: '7', - joinedAt: new Date(), - } - await MemberRepository.create(user1, mockIRepositoryOptions) - await MemberRepository.create(user2, mockIRepositoryOptions) - await MemberRepository.create(user3, mockIRepositoryOptions) - - await SequelizeTestUtils.refreshMaterializedViews(db) - - const members = await MemberRepository.findAndCountAll( - { filter: { scoreRange: [1, 6] } }, - mockIRepositoryOptions, - ) - - expect(members.rows.length).toEqual(2) - expect(members.rows.find((m) => m.username[PlatformType.SLACK][0] === 'test1').score).toEqual( - 1, - ) - expect(members.rows.find((m) => m.username[PlatformType.SLACK][0] === 'test2').score).toEqual( - 6, - ) - }) - - it('is successfully finding and counting all members, and scoreRange is gte than 7', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const user1 = { - username: { - [PlatformType.DISCORD]: { - username: 'test1', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 1', - score: '1', - joinedAt: new Date(), - } - const user2 = { - username: { - [PlatformType.DISCORD]: { - username: 'test2', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 2', - score: '6', - joinedAt: new Date(), - } - const user3 = { - username: { - [PlatformType.DISCORD]: { - username: 'test3', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 3', - score: '7', - joinedAt: new Date(), - } - await MemberRepository.create(user1, mockIRepositoryOptions) - await MemberRepository.create(user2, mockIRepositoryOptions) - await MemberRepository.create(user3, mockIRepositoryOptions) - - await SequelizeTestUtils.refreshMaterializedViews(db) - - const members = await MemberRepository.findAndCountAll( - { filter: { scoreRange: [7] } }, - mockIRepositoryOptions, - ) - - expect(members.rows.length).toEqual(1) - for (const member of members.rows) { - expect(member.score).toBeGreaterThanOrEqual(7) - } - }) - - it('is successfully find and counting members with various filters, computed attributes, and full options (filter, limit, offset and orderBy)', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const nodeTag = await mockIRepositoryOptions.database.tag.create({ - name: 'nodejs', - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - }) - const vueTag = await mockIRepositoryOptions.database.tag.create({ - name: 'vuejs', - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - }) - - const member1 = await MemberRepository.create( - { - username: { - [PlatformType.SLACK]: { - username: 'test1', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 1', - score: '1', - joinedAt: new Date(), - tags: [nodeTag.id], - reach: { - total: 15, - }, - }, - mockIRepositoryOptions, - ) - const member2 = await MemberRepository.create( - { - username: { - [PlatformType.SLACK]: { - username: 'test2', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 2', - score: '6', - joinedAt: new Date(), - tags: [nodeTag.id, vueTag.id], - reach: { - total: 55, - }, - }, - mockIRepositoryOptions, - ) - const member3 = await MemberRepository.create( - { - username: { - [PlatformType.SLACK]: { - username: 'test3', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 3', - score: '7', - joinedAt: new Date(), - tags: [vueTag.id], - reach: { - total: 124, - }, - }, - mockIRepositoryOptions, - ) - - await mockIRepositoryOptions.database.activity.bulkCreate([ - { - type: 'message', - platform: PlatformType.SLACK, - timestamp: new Date('2022-09-10'), - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - memberId: member1.id, - username: member1.username[PlatformType.SLACK], - sourceId: '#sourceId1', - sentiment: { - positive: 0.55, - negative: 0.0, - neutral: 0.45, - mixed: 0.0, - label: 'positive', - sentiment: 0.1, - }, - }, - { - type: 'message', - platform: PlatformType.SLACK, - timestamp: new Date('2022-09-11'), - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - memberId: member2.id, - username: member2.username[PlatformType.SLACK], - sourceId: '#sourceId2', - sentiment: { - positive: 0.01, - negative: 0.55, - neutral: 0.55, - mixed: 0.0, - label: 'negative', - sentiment: -0.54, - }, - }, - { - type: 'message', - platform: PlatformType.SLACK, - timestamp: new Date('2022-09-12'), - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - memberId: member2.id, - username: member2.username[PlatformType.SLACK], - sourceId: '#sourceId3', - sentiment: { - positive: 0.94, - negative: 0.0, - neutral: 0.06, - mixed: 0.0, - label: 'positive', - sentiment: 0.94, - }, - }, - { - type: 'message', - platform: PlatformType.SLACK, - timestamp: new Date('2022-09-13'), - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - memberId: member3.id, - username: member3.username[PlatformType.SLACK], - sourceId: '#sourceId4', - sentiment: { - positive: 0.42, - negative: 0.42, - neutral: 0.42, - mixed: 0.42, - label: 'positive', - sentiment: 0.42, - }, - }, - { - type: 'message', - platform: PlatformType.SLACK, - timestamp: new Date('2022-09-14'), - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - memberId: member3.id, - username: member3.username[PlatformType.SLACK], - sourceId: '#sourceId5', - sentiment: { - positive: 0.42, - negative: 0.42, - neutral: 0.42, - mixed: 0.42, - label: 'positive', - sentiment: 0.41, - }, - }, - { - type: 'message', - platform: PlatformType.SLACK, - timestamp: new Date('2022-09-15'), - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - memberId: member3.id, - username: member3.username[PlatformType.SLACK], - sourceId: '#sourceId6', - sentiment: { - positive: 0.42, - negative: 0.42, - neutral: 0.42, - mixed: 0.42, - label: 'positive', - sentiment: 0.18, - }, - }, - ]) - - await SequelizeTestUtils.refreshMaterializedViews(db) - - let members = await MemberRepository.findAndCountAll( - { - filter: {}, - limit: 15, - offset: 0, - orderBy: 'activityCount_DESC', - }, - mockIRepositoryOptions, - ) - expect(members.rows.length).toEqual(3) - expect(members.rows[0].activityCount).toEqual('3') - expect(members.rows[0].lastActive.toISOString()).toEqual('2022-09-15T00:00:00.000Z') - - expect(members.rows[1].activityCount).toEqual('2') - expect(members.rows[1].lastActive.toISOString()).toEqual('2022-09-12T00:00:00.000Z') - - expect(members.rows[2].activityCount).toEqual('1') - expect(members.rows[2].tags[0].name).toEqual('nodejs') - expect(members.rows[2].lastActive.toISOString()).toEqual('2022-09-10T00:00:00.000Z') - - expect(members.rows[1].tags.map((i) => i.name).sort()).toEqual(['nodejs', 'vuejs']) - expect(members.rows[0].tags[0].name).toEqual('vuejs') - - // filter and order by reach - members = await MemberRepository.findAndCountAll( - { - filter: { - reachRange: [55], - }, - limit: 15, - offset: 0, - orderBy: 'reach_DESC', - }, - mockIRepositoryOptions, - ) - - expect(members.rows.length).toEqual(2) - expect(members.rows[0].id).toEqual(member3.id) - expect(members.rows[1].id).toEqual(member2.id) - - // filter and sort by activity count - members = await MemberRepository.findAndCountAll( - { - filter: { - activityCountRange: [2], - }, - limit: 15, - offset: 0, - orderBy: 'activityCount_DESC', - }, - mockIRepositoryOptions, - ) - - expect(members.rows.length).toEqual(2) - expect(members.rows.map((i) => i.id)).toEqual([member3.id, member2.id]) - - // filter and sort by lastActive - members = await MemberRepository.findAndCountAll( - { - filter: { - lastActiveRange: ['2022-09-11'], - }, - limit: 15, - offset: 0, - orderBy: 'lastActive_DESC', - }, - mockIRepositoryOptions, - ) - - expect(members.rows.length).toEqual(2) - expect(members.rows.map((i) => i.id)).toEqual([member3.id, member2.id]) - - // filter and sort by averageSentiment (member1.avgSentiment = 0.1, member2.avgSentiment = 0.2, member3.avgSentiment = 0.34) - members = await MemberRepository.findAndCountAll( - { - filter: { - averageSentimentRange: [0.2], - }, - limit: 15, - offset: 0, - orderBy: 'averageSentiment_ASC', - }, - mockIRepositoryOptions, - ) - - expect(members.rows.length).toEqual(2) - expect(members.rows.map((i) => i.id)).toEqual([member2.id, member3.id]) - }) - }) - - describe('findAndCountAllv2 method', () => { - it('is successfully finding and counting all members, sortedBy activitiesCount DESC', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const member1 = await MemberRepository.create( - { - username: { [PlatformType.TWITTER]: 'test1' }, - displayName: 'Member 1', - score: '1', - joinedAt: new Date(), - }, - mockIRepositoryOptions, - ) - const member2 = await MemberRepository.create( - { - username: { [PlatformType.TWITTER]: 'test2' }, - displayName: 'Member 2', - score: '6', - joinedAt: new Date(), - }, - mockIRepositoryOptions, - ) - const member3 = await MemberRepository.create( - { - username: { [PlatformType.TWITTER]: 'test3' }, - displayName: 'Member 3', - score: '7', - joinedAt: new Date(), - }, - mockIRepositoryOptions, - ) - - await mockIRepositoryOptions.database.activity.bulkCreate([ - { - type: 'message', - platform: PlatformType.SLACK, - timestamp: new Date(), - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - username: 'test1', - memberId: member1.id, - sourceId: '#sourceId1', - }, - { - type: 'message', - platform: PlatformType.SLACK, - timestamp: new Date(), - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - username: 'test2', - memberId: member2.id, - sourceId: '#sourceId2', - }, - { - type: 'message', - platform: PlatformType.SLACK, - timestamp: new Date(), - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - username: 'test2', - memberId: member2.id, - sourceId: '#sourceId3', - }, - { - type: 'message', - platform: PlatformType.SLACK, - timestamp: new Date(), - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - username: 'test3', - memberId: member3.id, - sourceId: '#sourceId4', - }, - { - type: 'message', - platform: PlatformType.SLACK, - timestamp: new Date(), - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - username: 'test3', - memberId: member3.id, - sourceId: '#sourceId5', - }, - { - type: 'message', - platform: PlatformType.SLACK, - timestamp: new Date(), - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - username: 'test3', - memberId: member3.id, - sourceId: '#sourceId6', - }, - ]) - - await SequelizeTestUtils.refreshMaterializedViews(db) - - const members = await MemberRepository.findAndCountAllv2( - { filter: {}, orderBy: 'activityCount_DESC' }, - mockIRepositoryOptions, - ) - - expect(members.rows.length).toEqual(3) - expect(members.rows[0].activityCount).toEqual('3') - expect(members.rows[1].activityCount).toEqual('2') - expect(members.rows[2].activityCount).toEqual('1') - }) - - it('is successfully finding and counting all members, sortedBy numberOfOpenSourceContributions DESC', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - await MemberRepository.create( - { - username: { [PlatformType.TWITTER]: 'test1' }, - displayName: 'Member 1', - score: '1', - joinedAt: new Date(), - contributions: [ - { - id: 112529472, - url: 'https://github.com/bachman/pied-piper', - topics: ['compression', 'data', 'middle-out', 'Java'], - summary: 'Pied Piper: 10 commits in 1 day', - numberCommits: 10, - lastCommitDate: '2023-03-10', - firstCommitDate: '2023-03-01', - }, - { - id: 112529473, - url: 'https://github.com/bachman/aviato', - topics: ['Python', 'Django'], - summary: 'Aviato: 5 commits in 1 day', - numberCommits: 5, - lastCommitDate: '2023-02-25', - firstCommitDate: '2023-02-20', - }, - { - id: 112529476, - url: 'https://github.com/bachman/erlichbot', - topics: ['Python', 'Slack API'], - summary: 'ErlichBot: 2 commits in 1 day', - numberCommits: 2, - lastCommitDate: '2023-01-25', - firstCommitDate: '2023-01-24', - }, - ], - }, - mockIRepositoryOptions, - ) - await MemberRepository.create( - { - username: { [PlatformType.TWITTER]: 'test2' }, - displayName: 'Member 2', - score: '6', - joinedAt: new Date(), - contributions: [ - { - id: 112529473, - url: 'https://github.com/bighead/silicon-valley', - topics: ['TV Shows', 'Comedy', 'Startups'], - summary: 'Silicon Valley: 50 commits in 2 weeks', - numberCommits: 50, - lastCommitDate: '02/01/2023', - firstCommitDate: '01/17/2023', - }, - { - id: 112529474, - url: 'https://github.com/bighead/startup-ideas', - topics: ['Ideas', 'Startups'], - summary: 'Startup Ideas: 20 commits in 1 week', - numberCommits: 20, - lastCommitDate: '03/01/2023', - firstCommitDate: '02/22/2023', - }, - ], - }, - mockIRepositoryOptions, - ) - await MemberRepository.create( - { - username: { [PlatformType.TWITTER]: 'test3' }, - displayName: 'Member 3', - score: '7', - joinedAt: new Date(), - }, - mockIRepositoryOptions, - ) - - await SequelizeTestUtils.refreshMaterializedViews(db) - - const members = await MemberRepository.findAndCountAllv2( - { filter: {}, orderBy: 'numberOfOpenSourceContributions_DESC' }, - mockIRepositoryOptions, - ) - - expect(members.rows.length).toEqual(3) - expect(members.rows[0].numberOfOpenSourceContributions).toEqual(3) - expect(members.rows[1].numberOfOpenSourceContributions).toEqual(2) - expect(members.rows[2].numberOfOpenSourceContributions).toEqual(0) - }) - - it('is successfully finding and counting all members, numberOfOpenSourceContributions range gte 3', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - await MemberRepository.create( - { - username: { - [PlatformType.TWITTER]: { - username: 'test1', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 1', - score: '1', - joinedAt: new Date(), - contributions: [ - { - id: 112529472, - url: 'https://github.com/bachman/pied-piper', - topics: ['compression', 'data', 'middle-out', 'Java'], - summary: 'Pied Piper: 10 commits in 1 day', - numberCommits: 10, - lastCommitDate: '2023-03-10', - firstCommitDate: '2023-03-01', - }, - { - id: 112529473, - url: 'https://github.com/bachman/aviato', - topics: ['Python', 'Django'], - summary: 'Aviato: 5 commits in 1 day', - numberCommits: 5, - lastCommitDate: '2023-02-25', - firstCommitDate: '2023-02-20', - }, - { - id: 112529476, - url: 'https://github.com/bachman/erlichbot', - topics: ['Python', 'Slack API'], - summary: 'ErlichBot: 2 commits in 1 day', - numberCommits: 2, - lastCommitDate: '2023-01-25', - firstCommitDate: '2023-01-24', - }, - { - id: 112529473, - url: 'https://github.com/bighead/silicon-valley', - topics: ['TV Shows', 'Comedy', 'Startups'], - summary: 'Silicon Valley: 50 commits in 2 weeks', - numberCommits: 50, - lastCommitDate: '02/01/2023', - firstCommitDate: '01/17/2023', - }, - ], - }, - mockIRepositoryOptions, - ) - await MemberRepository.create( - { - username: { - [PlatformType.TWITTER]: { - username: 'test2', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 2', - score: '6', - joinedAt: new Date(), - contributions: [ - { - id: 112529473, - url: 'https://github.com/bighead/silicon-valley', - topics: ['TV Shows', 'Comedy', 'Startups'], - summary: 'Silicon Valley: 50 commits in 2 weeks', - numberCommits: 50, - lastCommitDate: '02/01/2023', - firstCommitDate: '01/17/2023', - }, - { - id: 112529474, - url: 'https://github.com/bighead/startup-ideas', - topics: ['Ideas', 'Startups'], - summary: 'Startup Ideas: 20 commits in 1 week', - numberCommits: 20, - lastCommitDate: '03/01/2023', - firstCommitDate: '02/22/2023', - }, - ], - }, - mockIRepositoryOptions, - ) - await MemberRepository.create( - { - username: { - [PlatformType.TWITTER]: { - username: 'test3', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 3', - score: '7', - joinedAt: new Date(), - }, - mockIRepositoryOptions, - ) - - await SequelizeTestUtils.refreshMaterializedViews(db) - - const members = await MemberRepository.findAndCountAllv2( - { - filter: { - and: [ - { - and: [ - { - numberOfOpenSourceContributions: { - gte: 3, - }, - }, - ], - }, - ], - }, - }, - mockIRepositoryOptions, - ) - - expect(members.rows.length).toEqual(1) - expect(members.rows[0].numberOfOpenSourceContributions).toEqual(4) - }) - - it('is successfully finding and counting all members, numberOfOpenSourceContributions range gte 2 and sort by asc', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - await MemberRepository.create( - { - username: { [PlatformType.TWITTER]: 'test1' }, - displayName: 'Member 1', - score: '1', - joinedAt: new Date(), - contributions: [ - { - id: 112529472, - url: 'https://github.com/bachman/pied-piper', - topics: ['compression', 'data', 'middle-out', 'Java'], - summary: 'Pied Piper: 10 commits in 1 day', - numberCommits: 10, - lastCommitDate: '2023-03-10', - firstCommitDate: '2023-03-01', - }, - { - id: 112529473, - url: 'https://github.com/bachman/aviato', - topics: ['Python', 'Django'], - summary: 'Aviato: 5 commits in 1 day', - numberCommits: 5, - lastCommitDate: '2023-02-25', - firstCommitDate: '2023-02-20', - }, - { - id: 112529476, - url: 'https://github.com/bachman/erlichbot', - topics: ['Python', 'Slack API'], - summary: 'ErlichBot: 2 commits in 1 day', - numberCommits: 2, - lastCommitDate: '2023-01-25', - firstCommitDate: '2023-01-24', - }, - { - id: 112529473, - url: 'https://github.com/bighead/silicon-valley', - topics: ['TV Shows', 'Comedy', 'Startups'], - summary: 'Silicon Valley: 50 commits in 2 weeks', - numberCommits: 50, - lastCommitDate: '02/01/2023', - firstCommitDate: '01/17/2023', - }, - ], - }, - mockIRepositoryOptions, - ) - await MemberRepository.create( - { - username: { [PlatformType.TWITTER]: 'test2' }, - displayName: 'Member 2', - score: '6', - joinedAt: new Date(), - contributions: [ - { - id: 112529473, - url: 'https://github.com/bighead/silicon-valley', - topics: ['TV Shows', 'Comedy', 'Startups'], - summary: 'Silicon Valley: 50 commits in 2 weeks', - numberCommits: 50, - lastCommitDate: '02/01/2023', - firstCommitDate: '01/17/2023', - }, - { - id: 112529474, - url: 'https://github.com/bighead/startup-ideas', - topics: ['Ideas', 'Startups'], - summary: 'Startup Ideas: 20 commits in 1 week', - numberCommits: 20, - lastCommitDate: '03/01/2023', - firstCommitDate: '02/22/2023', - }, - ], - }, - mockIRepositoryOptions, - ) - await MemberRepository.create( - { - username: { [PlatformType.TWITTER]: 'test3' }, - displayName: 'Member 3', - score: '7', - joinedAt: new Date(), - }, - mockIRepositoryOptions, - ) - - await SequelizeTestUtils.refreshMaterializedViews(db) - const members = await MemberRepository.findAndCountAllv2( - { - filter: { - and: [ - { - and: [ - { - numberOfOpenSourceContributions: { - gte: 2, - }, - }, - ], - }, - ], - }, - orderBy: 'numberOfOpenSourceContributions_ASC', - }, - mockIRepositoryOptions, - ) - - expect(members.rows.length).toEqual(2) - expect(members.rows[0].numberOfOpenSourceContributions).toEqual(2) - expect(members.rows[1].numberOfOpenSourceContributions).toEqual(4) - }) - - it('is successfully finding and counting all members, and tags [nodejs, vuejs]', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const nodeTag = await mockIRepositoryOptions.database.tag.create({ - name: 'nodejs', - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - }) - const vueTag = await mockIRepositoryOptions.database.tag.create({ - name: 'vuejs', - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - }) - - await MemberRepository.create( - { - username: { - [PlatformType.TWITTER]: { - username: 'test1', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 1', - score: '1', - joinedAt: new Date(), - }, - mockIRepositoryOptions, - ) - await MemberRepository.create( - { - username: { - [PlatformType.TWITTER]: { - username: 'test2', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 2', - score: '6', - joinedAt: new Date(), - tags: [nodeTag.id, vueTag.id], - }, - mockIRepositoryOptions, - ) - await MemberRepository.create( - { - username: { - [PlatformType.GITHUB]: { - username: 'test3', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 3', - score: '7', - joinedAt: new Date(), - }, - mockIRepositoryOptions, - ) - - await SequelizeTestUtils.refreshMaterializedViews(db) - - const members = await MemberRepository.findAndCountAllv2( - { - filter: { - and: [ - { - tags: { - contains: [nodeTag.id, vueTag.id], - }, - }, - ], - }, - }, - mockIRepositoryOptions, - ) - const member2 = members.rows.find((m) => m.username[PlatformType.TWITTER].includes('test2')) - expect(members.rows.length).toEqual(1) - expect(member2.tags.map((t) => t.name)).toEqual(expect.arrayContaining(['nodejs', 'vuejs'])) - }) - - it('is successfully finding and counting all members, and tags [nodejs]', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const nodeTag = await mockIRepositoryOptions.database.tag.create({ - name: 'nodejs', - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - }) - const vueTag = await mockIRepositoryOptions.database.tag.create({ - name: 'vuejs', - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - }) - - await MemberRepository.create( - { - username: { - [PlatformType.GITHUB]: { - username: 'test1', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 1', - score: '1', - joinedAt: new Date(), - tags: [nodeTag.id], - }, - mockIRepositoryOptions, - ) - await MemberRepository.create( - { - username: { - [PlatformType.GITHUB]: { - username: 'test2', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 2', - score: '6', - joinedAt: new Date(), - tags: [nodeTag.id, vueTag.id], - }, - mockIRepositoryOptions, - ) - await MemberRepository.create( - { - username: { - [PlatformType.GITHUB]: { - username: 'test3', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 3', - score: '7', - joinedAt: new Date(), - }, - mockIRepositoryOptions, - ) - - await SequelizeTestUtils.refreshMaterializedViews(db) - - const members = await MemberRepository.findAndCountAllv2( - { - filter: { - and: [ - { - tags: { - contains: [nodeTag.id], - }, - }, - ], - }, - }, - mockIRepositoryOptions, - ) - const member1 = members.rows.find((m) => m.username[PlatformType.GITHUB].includes('test1')) - const member2 = members.rows.find((m) => m.username[PlatformType.GITHUB].includes('test2')) - - expect(members.rows.length).toEqual(2) - expect(member1.tags[0].name).toEqual('nodejs') - expect(member2.tags.map((t) => t.name)).toEqual(expect.arrayContaining(['nodejs', 'vuejs'])) - }) - - it('is successfully finding and counting all members, and organisations [crowd.dev, pied piper]', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const crowd = await OrganizationRepository.create( - { - identities: [ - { - name: 'crowd.dev', - url: 'https://crowd.dev', - platform: 'crowd', - }, - ], - displayName: 'crowd.dev', - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - }, - mockIRepositoryOptions, - ) - const pp = await OrganizationRepository.create( - { - identities: [ - { - name: 'pied piper', - url: 'https://piedpiper.com', - platform: 'crowd', - }, - ], - displayName: 'pied piper', - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - }, - mockIRepositoryOptions, - ) - - await MemberRepository.create( - { - username: { - [PlatformType.SLACK]: { - username: 'test1', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 1', - score: '1', - joinedAt: new Date(), - }, - mockIRepositoryOptions, - ) - await MemberRepository.create( - { - username: { - [PlatformType.SLACK]: { - username: 'test2', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 2', - score: '6', - joinedAt: new Date(), - organizations: [crowd.id, pp.id], - }, - mockIRepositoryOptions, - ) - await MemberRepository.create( - { - username: { - [PlatformType.SLACK]: { - username: 'test3', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 3', - score: '7', - joinedAt: new Date(), - }, - mockIRepositoryOptions, - ) - - await SequelizeTestUtils.refreshMaterializedViews(db) - - const members = await MemberRepository.findAndCountAllv2( - { - filter: { - and: [ - { - organizations: { - contains: [crowd.id, pp.id], - }, - }, - ], - }, - }, - mockIRepositoryOptions, - ) - const member2 = members.rows.find((m) => m.username[PlatformType.SLACK].includes('test2')) - expect(members.rows.length).toEqual(1) - expect(member2.organizations.map((o) => o.displayName)).toEqual( - expect.arrayContaining(['crowd.dev', 'pied piper']), - ) - }) - - it('is successfully finding and counting all members, and scoreRange is gte than 7', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const user1 = { - username: { - [PlatformType.DISCORD]: { - username: 'test1', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 1', - score: '1', - joinedAt: new Date(), - } - const user2 = { - username: { - [PlatformType.DISCORD]: { - username: 'test2', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 2', - score: '6', - joinedAt: new Date(), - } - const user3 = { - username: { - [PlatformType.DISCORD]: { - username: 'test3', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 3', - score: '7', - joinedAt: new Date(), - } - await MemberRepository.create(user1, mockIRepositoryOptions) - await MemberRepository.create(user2, mockIRepositoryOptions) - await MemberRepository.create(user3, mockIRepositoryOptions) - - await SequelizeTestUtils.refreshMaterializedViews(db) - - const members = await MemberRepository.findAndCountAllv2( - { - filter: { - and: [ - { - and: [ - { - score: { - gte: 7, - }, - }, - ], - }, - ], - }, - }, - mockIRepositoryOptions, - ) - - expect(members.rows.length).toEqual(1) - for (const member of members.rows) { - expect(member.score).toBeGreaterThanOrEqual(7) - } - }) - - it('is successfully find and counting members with various filters, computed attributes, and full options (filter, limit, offset and orderBy)', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const nodeTag = await mockIRepositoryOptions.database.tag.create({ - name: 'nodejs', - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - }) - const vueTag = await mockIRepositoryOptions.database.tag.create({ - name: 'vuejs', - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - }) - - const member1 = await MemberRepository.create( - { - username: { - [PlatformType.SLACK]: { - username: 'test1', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 1', - score: '1', - joinedAt: new Date(), - tags: [nodeTag.id], - reach: { - total: 15, - }, - }, - mockIRepositoryOptions, - ) - const member2 = await MemberRepository.create( - { - username: { - [PlatformType.SLACK]: { - username: 'test2', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 2', - score: '6', - joinedAt: new Date(), - tags: [nodeTag.id, vueTag.id], - reach: { - total: 55, - }, - }, - mockIRepositoryOptions, - ) - const member3 = await MemberRepository.create( - { - username: { - [PlatformType.SLACK]: { - username: 'test3', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 3', - score: '7', - joinedAt: new Date(), - tags: [vueTag.id], - reach: { - total: 124, - }, - }, - mockIRepositoryOptions, - ) - - await mockIRepositoryOptions.database.activity.bulkCreate([ - { - type: 'message', - platform: PlatformType.SLACK, - timestamp: new Date('2022-09-10'), - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - memberId: member1.id, - username: member1.username[PlatformType.SLACK], - sourceId: '#sourceId1', - sentiment: { - positive: 0.55, - negative: 0.0, - neutral: 0.45, - mixed: 0.0, - label: 'positive', - sentiment: 0.1, - }, - }, - { - type: 'message', - platform: PlatformType.SLACK, - timestamp: new Date('2022-09-11'), - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - memberId: member2.id, - username: member2.username[PlatformType.SLACK], - sourceId: '#sourceId2', - sentiment: { - positive: 0.01, - negative: 0.55, - neutral: 0.55, - mixed: 0.0, - label: 'negative', - sentiment: -0.54, - }, - }, - { - type: 'message', - platform: PlatformType.SLACK, - timestamp: new Date('2022-09-12'), - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - memberId: member2.id, - username: member2.username[PlatformType.SLACK], - sourceId: '#sourceId3', - sentiment: { - positive: 0.94, - negative: 0.0, - neutral: 0.06, - mixed: 0.0, - label: 'positive', - sentiment: 0.94, - }, - }, - { - type: 'message', - platform: PlatformType.SLACK, - timestamp: new Date('2022-09-13'), - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - memberId: member3.id, - username: member3.username[PlatformType.SLACK], - sourceId: '#sourceId4', - sentiment: { - positive: 0.42, - negative: 0.42, - neutral: 0.42, - mixed: 0.42, - label: 'positive', - sentiment: 0.42, - }, - }, - { - type: 'message', - platform: PlatformType.SLACK, - timestamp: new Date('2022-09-14'), - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - memberId: member3.id, - username: member3.username[PlatformType.SLACK], - sourceId: '#sourceId5', - sentiment: { - positive: 0.42, - negative: 0.42, - neutral: 0.42, - mixed: 0.42, - label: 'positive', - sentiment: 0.41, - }, - }, - { - type: 'message', - platform: PlatformType.SLACK, - timestamp: new Date('2022-09-15'), - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - memberId: member3.id, - username: member3.username[PlatformType.SLACK], - sourceId: '#sourceId6', - sentiment: { - positive: 0.42, - negative: 0.42, - neutral: 0.42, - mixed: 0.42, - label: 'positive', - sentiment: 0.18, - }, - }, - ]) - - await SequelizeTestUtils.refreshMaterializedViews(db) - - let members = await MemberRepository.findAndCountAllv2( - { - filter: {}, - limit: 15, - offset: 0, - orderBy: 'activityCount_DESC', - }, - mockIRepositoryOptions, - ) - expect(members.rows.length).toEqual(3) - expect(members.rows[0].activityCount).toEqual('3') - expect(members.rows[0].lastActive.toISOString()).toEqual('2022-09-15T00:00:00.000Z') - - expect(members.rows[1].activityCount).toEqual('2') - expect(members.rows[1].lastActive.toISOString()).toEqual('2022-09-12T00:00:00.000Z') - - expect(members.rows[2].activityCount).toEqual('1') - expect(members.rows[2].tags[0].name).toEqual('nodejs') - expect(members.rows[2].lastActive.toISOString()).toEqual('2022-09-10T00:00:00.000Z') - - expect(members.rows[1].tags.map((i) => i.name).sort()).toEqual(['nodejs', 'vuejs']) - expect(members.rows[0].tags[0].name).toEqual('vuejs') - - // filter and order by reach - members = await MemberRepository.findAndCountAllv2( - { - filter: { - and: [ - { - and: [ - { - reach: { - gte: 55, - }, - }, - ], - }, - ], - }, - limit: 15, - offset: 0, - orderBy: 'reach_DESC', - }, - mockIRepositoryOptions, - ) - - expect(members.rows.length).toEqual(2) - expect(members.rows[0].id).toEqual(member3.id) - expect(members.rows[1].id).toEqual(member2.id) - - // filter and sort by activity count - members = await MemberRepository.findAndCountAllv2( - { - filter: { - and: [ - { - and: [ - { - activityCount: { - gte: 2, - }, - }, - ], - }, - ], - }, - limit: 15, - offset: 0, - orderBy: 'activityCount_DESC', - }, - mockIRepositoryOptions, - ) - - expect(members.rows.length).toEqual(2) - expect(members.rows.map((i) => i.id)).toEqual([member3.id, member2.id]) - - // filter and sort by lastActive - members = await MemberRepository.findAndCountAllv2( - { - filter: { - and: [ - { - and: [ - { - lastActive: { - gte: '2022-09-11', - }, - }, - ], - }, - ], - }, - limit: 15, - offset: 0, - orderBy: 'lastActive_DESC', - }, - mockIRepositoryOptions, - ) - - expect(members.rows.length).toEqual(2) - expect(members.rows.map((i) => i.id)).toEqual([member3.id, member2.id]) - - // filter and sort by averageSentiment (member1.avgSentiment = 0.1, member2.avgSentiment = 0.2, member3.avgSentiment = 0.34) - members = await MemberRepository.findAndCountAllv2( - { - filter: { - and: [ - { - and: [ - { - averageSentiment: { - gte: 0.2, - }, - }, - ], - }, - ], - }, - limit: 15, - offset: 0, - orderBy: 'averageSentiment_ASC', - }, - mockIRepositoryOptions, - ) - - expect(members.rows.length).toEqual(2) - expect(members.rows.map((i) => i.id)).toEqual([member2.id, member3.id]) - }) - }) - - describe('update method', () => { - it('Should succesfully update previously created member', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const member1 = { - username: { - [PlatformType.DISCORD]: { - username: 'test1', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 1', - score: '1', - joinedAt: '2021-05-27T15:14:30Z', - } - let cloned = lodash.cloneDeep(member1) - const returnedMember = await MemberRepository.create(cloned, mockIRepositoryOptions) - - const updateFields = { - username: { - [PlatformType.GITHUB]: { - username: 'anil_github', - integrationId: generateUUIDv1(), - }, - }, - emails: ['lala@l.com'], - score: 10, - attributes: { - [PlatformType.GITHUB]: { - name: 'Quoc-Anh Nguyen', - isHireable: true, - url: 'https://github.com/imcvampire', - websiteUrl: 'https://imcvampire.js.org/', - bio: 'Lazy geek', - location: 'Helsinki, Finland', - actions: [ - { - score: 2, - timestamp: '2021-05-27T15:13:30Z', - }, - ], - }, - [PlatformType.TWITTER]: { - profile_url: 'https://twitter.com/imcvampire', - url: 'https://twitter.com/imcvampire', - }, - }, - joinedAt: '2021-06-27T15:14:30Z', - location: 'Istanbul', - } - - cloned = lodash.cloneDeep(updateFields) - const updatedMember = await MemberRepository.update( - returnedMember.id, - cloned, - mockIRepositoryOptions, - ) - - // check updatedAt field looks ok or not. Should be greater than createdAt - expect(updatedMember.updatedAt.getTime()).toBeGreaterThan(updatedMember.createdAt.getTime()) - - updatedMember.createdAt = updatedMember.createdAt.toISOString().split('T')[0] - updatedMember.updatedAt = updatedMember.updatedAt.toISOString().split('T')[0] - - const expectedMemberCreated = { - id: returnedMember.id, - username: mapUsername({ - ...updateFields.username, - ...member1.username, - }), - identities: ['discord', 'github'], - displayName: returnedMember.displayName, - attributes: updateFields.attributes, - emails: updateFields.emails, - score: updateFields.score, - lastEnriched: null, - enrichedBy: [], - contributions: null, - organizations: [], - importHash: null, - createdAt: SequelizeTestUtils.getNowWithoutTime(), - updatedAt: SequelizeTestUtils.getNowWithoutTime(), - deletedAt: null, - tenantId: mockIRepositoryOptions.currentTenant.id, - segments: mockIRepositoryOptions.currentSegments, - createdById: mockIRepositoryOptions.currentUser.id, - updatedById: mockIRepositoryOptions.currentUser.id, - reach: { total: -1 }, - notes: [], - tasks: [], - activeOn: [], - activityTypes: [], - joinedAt: new Date(updateFields.joinedAt), - tags: [], - noMerge: [], - toMerge: [], - activityCount: 0, - activeDaysCount: 0, - averageSentiment: 0, - numberOfOpenSourceContributions: 0, - lastActive: null, - lastActivity: null, - affiliations: [], - manuallyCreated: false, - } - - expect(updatedMember).toStrictEqual(expectedMemberCreated) - }) - - it('Should update successfuly but return without relations when doPopulateRelations=false', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const member1 = { - username: { - [PlatformType.DISCORD]: { - username: 'test1', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 1', - score: '1', - joinedAt: '2021-05-27T15:14:30Z', - } - const returnedMember = await MemberRepository.create(member1, mockIRepositoryOptions) - - const updateFields = { - username: { - [PlatformType.GITHUB]: { - username: 'anil_github', - integrationId: generateUUIDv1(), - }, - }, - emails: ['lala@l.com'], - score: 10, - attributes: { - [PlatformType.GITHUB]: { - name: 'Quoc-Anh Nguyen', - isHireable: true, - url: 'https://github.com/imcvampire', - websiteUrl: 'https://imcvampire.js.org/', - bio: 'Lazy geek', - location: 'Helsinki, Finland', - actions: [ - { - score: 2, - timestamp: '2021-05-27T15:13:30Z', - }, - ], - }, - [PlatformType.TWITTER]: { - profile_url: 'https://twitter.com/imcvampire', - url: 'https://twitter.com/imcvampire', - }, - }, - joinedAt: '2021-06-27T15:14:30Z', - location: 'Istanbul', - } - - const updatedMember = await MemberRepository.update( - returnedMember.id, - updateFields, - mockIRepositoryOptions, - false, - ) - - // check updatedAt field looks ok or not. Should be greater than createdAt - expect(updatedMember.updatedAt.getTime()).toBeGreaterThan(updatedMember.createdAt.getTime()) - - updatedMember.createdAt = updatedMember.createdAt.toISOString().split('T')[0] - updatedMember.updatedAt = updatedMember.updatedAt.toISOString().split('T')[0] - - const expectedMemberCreated = { - id: returnedMember.id, - username: mapUsername({ - [PlatformType.DISCORD]: { - username: 'test1', - integrationId: generateUUIDv1(), - }, - [PlatformType.GITHUB]: { - username: 'anil_github', - integrationId: generateUUIDv1(), - }, - }), - displayName: returnedMember.displayName, - attributes: updateFields.attributes, - lastEnriched: null, - enrichedBy: [], - organizations: [], - contributions: null, - emails: updateFields.emails, - score: updateFields.score, - importHash: null, - createdAt: SequelizeTestUtils.getNowWithoutTime(), - updatedAt: SequelizeTestUtils.getNowWithoutTime(), - deletedAt: null, - tenantId: mockIRepositoryOptions.currentTenant.id, - segments: mockIRepositoryOptions.currentSegments, - createdById: mockIRepositoryOptions.currentUser.id, - updatedById: mockIRepositoryOptions.currentUser.id, - reach: { total: -1 }, - joinedAt: new Date(updateFields.joinedAt), - affiliations: [], - manuallyCreated: false, - } - - expect(updatedMember).toStrictEqual(expectedMemberCreated) - }) - - it('Should successfully update member with given tags', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const tag1 = await TagRepository.create({ name: 'tag1' }, mockIRepositoryOptions) - const tag2 = await TagRepository.create({ name: 'tag2' }, mockIRepositoryOptions) - const tag3 = await TagRepository.create({ name: 'tag3' }, mockIRepositoryOptions) - - // Create member with tag3 - let member1 = await MemberRepository.create( - { - username: { - [PlatformType.DISCORD]: { - username: 'test1', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 1', - score: '1', - joinedAt: new Date(), - tags: [tag3.id], - }, - mockIRepositoryOptions, - ) - - // When feeding tags attribute to update, update method will overwrite the member's tags with new given tags - // member1 is expected to have [tag1,tag2] after update - member1 = await MemberRepository.update( - member1.id, - { tags: [tag1.id, tag2.id] }, - mockIRepositoryOptions, - ) - - member1.createdAt = member1.createdAt.toISOString().split('T')[0] - member1.updatedAt = member1.updatedAt.toISOString().split('T')[0] - - member1.tags = member1.tags.map((i) => i.get({ plain: true })) - - // strip members field from tags created to expect. - // we won't be returning second level relationships. - const { members: _tag1Members, ...tag1Plain } = tag1 - const { members: _tag2Members, ...tag2Plain } = tag2 - - const expectedMemberCreated = { - id: member1.id, - username: member1.username, - displayName: member1.displayName, - identities: ['discord'], - attributes: {}, - emails: member1.emails, - score: member1.score, - organizations: [], - lastEnriched: null, - enrichedBy: [], - contributions: null, - importHash: null, - createdAt: SequelizeTestUtils.getNowWithoutTime(), - updatedAt: SequelizeTestUtils.getNowWithoutTime(), - deletedAt: null, - tenantId: mockIRepositoryOptions.currentTenant.id, - segments: mockIRepositoryOptions.currentSegments, - createdById: mockIRepositoryOptions.currentUser.id, - updatedById: mockIRepositoryOptions.currentUser.id, - reach: { total: -1 }, - notes: [], - tasks: [], - activeOn: [], - activityTypes: [], - joinedAt: new Date(member1.joinedAt), - tags: [tag1Plain, tag2Plain], - noMerge: [], - toMerge: [], - activityCount: 0, - activeDaysCount: 0, - averageSentiment: 0, - numberOfOpenSourceContributions: 0, - lastActive: null, - lastActivity: null, - affiliations: [], - manuallyCreated: false, - } - - expect(member1).toStrictEqual(expectedMemberCreated) - }) - - it('Should successfully update member with given organizations', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const org1 = await OrganizationRepository.create( - { - displayName: 'crowd.dev', - identities: [{ name: 'crowd.dev', url: 'https://crowd.dev', platform: 'crowd' }], - }, - mockIRepositoryOptions, - ) - const org2 = await OrganizationRepository.create( - { - displayName: 'pied piper', - identities: [{ name: 'pied piper', url: 'https://piedpiper.com', platform: 'crowd' }], - }, - mockIRepositoryOptions, - ) - const org3 = await OrganizationRepository.create( - { - displayName: 'hooli', - identities: [{ name: 'hooli', url: 'https://hooli.com', platform: 'crowd' }], - }, - mockIRepositoryOptions, - ) - - // Create member with tag3 - let member1 = await MemberRepository.create( - { - username: { - [PlatformType.DISCORD]: { - username: 'test1', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 1', - joinedAt: new Date(), - organizations: [org3.id], - }, - mockIRepositoryOptions, - ) - - // When feeding organizations attribute to update, update method will overwrite the member's organizations with new given orgs - // member1 is expected to have [org1,org2] after update - member1 = await MemberRepository.update( - member1.id, - { organizations: [org1.id, org2.id], organizationsReplace: true }, - mockIRepositoryOptions, - ) - - member1.createdAt = member1.createdAt.toISOString().split('T')[0] - member1.updatedAt = member1.updatedAt.toISOString().split('T')[0] - - member1.organizations = member1.organizations.map((i) => - SequelizeTestUtils.objectWithoutKey(i.get({ plain: true }), ['memberOrganizations']), - ) - - // // sort member organizations by createdAt - // member1.organizations.sort((a, b) => { - // return a.createdAt < b.createdAt ? -1 : 1 - // }) - - // strip members field from tags created to expect. - // we won't be returning second level relationships. - const { memberCount: _tag1Members, ...org1Plain } = org1 - const { memberCount: _tag2Members, ...org2Plain } = org2 - - const expectedMemberCreated = { - id: member1.id, - username: member1.username, - displayName: member1.displayName, - identities: ['discord'], - attributes: {}, - emails: member1.emails, - score: member1.score, - tags: [], - lastEnriched: null, - enrichedBy: [], - contributions: null, - importHash: null, - createdAt: SequelizeTestUtils.getNowWithoutTime(), - updatedAt: SequelizeTestUtils.getNowWithoutTime(), - deletedAt: null, - tenantId: mockIRepositoryOptions.currentTenant.id, - segments: mockIRepositoryOptions.currentSegments, - createdById: mockIRepositoryOptions.currentUser.id, - updatedById: mockIRepositoryOptions.currentUser.id, - activeOn: [], - activityTypes: [], - reach: { total: -1 }, - joinedAt: new Date(member1.joinedAt), - organizations: [ - SequelizeTestUtils.objectWithoutKey(org1Plain, [ - 'lastActive', - 'identities', - 'activeOn', - 'joinedAt', - 'activityCount', - 'segments', - 'weakIdentities', - ]), - SequelizeTestUtils.objectWithoutKey(org2Plain, [ - 'lastActive', - 'identities', - 'activeOn', - 'joinedAt', - 'activityCount', - 'segments', - 'weakIdentities', - ]), - ], - noMerge: [], - toMerge: [], - notes: [], - tasks: [], - activityCount: 0, - activeDaysCount: 0, - averageSentiment: 0, - numberOfOpenSourceContributions: 0, - lastActive: null, - lastActivity: null, - affiliations: [], - manuallyCreated: false, - } - - member1.organizations = member1.organizations.sort((a, b) => { - if (a.displayName < b.displayName) { - return -1 - } - if (a.displayName > b.displayName) { - return 1 - } - return 0 - }) - - expect(member1).toStrictEqual(expectedMemberCreated) - }) - - it('Should succesfully update member with notes', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const notes1 = await NoteRepository.create( - { - body: 'note1', - }, - mockIRepositoryOptions, - ) - - const notes2 = await NoteRepository.create( - { - body: 'note2', - }, - mockIRepositoryOptions, - ) - - const member2add = { - username: { - [PlatformType.DISCORD]: { - username: 'anil', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 1', - joinedAt: '2020-05-27T15:13:30Z', - } - - const memberCreated = await MemberRepository.create(member2add, mockIRepositoryOptions) - const memberUpdated = await MemberRepository.update( - memberCreated.id, - { notes: [notes1.id, notes2.id] }, - mockIRepositoryOptions, - ) - expect(memberCreated.notes).toHaveLength(0) - expect(memberUpdated.notes).toHaveLength(2) - expect(memberUpdated.notes[0].id).toEqual(notes1.id) - expect(memberUpdated.notes[1].id).toEqual(notes2.id) - }) - - it('Should succesfully update member with tasks', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const tasks1 = await TaskRepository.create( - { - name: 'task1', - }, - mockIRepositoryOptions, - ) - - const task2 = await TaskRepository.create( - { - name: 'task2', - }, - mockIRepositoryOptions, - ) - - const member2add = { - username: { - [PlatformType.DISCORD]: { - username: 'anil', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 1', - joinedAt: '2020-05-27T15:13:30Z', - } - - const memberCreated = await MemberRepository.create(member2add, mockIRepositoryOptions) - expect(memberCreated.tasks).toHaveLength(0) - - const memberUpdated = await MemberRepository.update( - memberCreated.id, - { tasks: [tasks1.id, task2.id] }, - mockIRepositoryOptions, - ) - expect(memberUpdated.tasks).toHaveLength(2) - expect(memberUpdated.tasks.find((t) => t.id === tasks1.id)).not.toBeUndefined() - expect(memberUpdated.tasks.find((t) => t.id === task2.id)).not.toBeUndefined() - }) - - it('Should throw 404 error when trying to update non existent member', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const { randomUUID } = require('crypto') - - await expect(() => - MemberRepository.update(randomUUID(), { location: 'test' }, mockIRepositoryOptions), - ).rejects.toThrowError(new Error404()) - }) - - it('Should throw a sequelize foreign key error when trying to update a member with a non existing tag', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const { randomUUID } = require('crypto') - - const member1 = await MemberRepository.create( - { - username: { - [PlatformType.DISCORD]: { - username: 'test1', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 1', - score: '1', - joinedAt: new Date(), - }, - mockIRepositoryOptions, - ) - - await expect(() => - MemberRepository.update(member1.id, { tags: [randomUUID()] }, mockIRepositoryOptions), - ).rejects.toThrow() - }) - - it('Should succesfully update member organization affiliations', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - const segmentRepo = new SegmentRepository(mockIRepositoryOptions) - - const segment1 = await segmentRepo.create({ - name: 'Crowd.dev - Segment1', - url: '', - parentName: 'Crowd.dev - Segment1', - grandparentName: 'Crowd.dev - Segment1', - slug: 'crowd.dev-1', - parentSlug: 'crowd.dev-1', - grandparentSlug: 'crowd.dev-1', - status: SegmentStatus.ACTIVE, - sourceId: null, - sourceParentId: null, - }) - - const segment2 = await segmentRepo.create({ - name: 'Crowd.dev - Segment2', - url: '', - parentName: 'Crowd.dev - Segment2', - grandparentName: 'Crowd.dev - Segment2', - slug: 'crowd.dev-2', - parentSlug: 'crowd.dev-2', - grandparentSlug: 'crowd.dev-2', - status: SegmentStatus.ACTIVE, - sourceId: null, - sourceParentId: null, - }) - - const org1 = await OrganizationRepository.create( - { - displayName: 'crowd.dev', - }, - mockIRepositoryOptions, - ) - - const member2add = { - username: { - [PlatformType.DISCORD]: { - username: 'anil', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 1', - joinedAt: '2020-05-27T15:13:30Z', - affiliations: [ - { - segmentId: segment1.id, - organizationId: org1.id, - }, - { - segmentId: segment2.id, - organizationId: null, - }, - ], - } - - const memberCreated = await MemberRepository.create(member2add, mockIRepositoryOptions) - expect(memberCreated.affiliations).toHaveLength(2) - - // removes segment1 affiliation, and set segment2 affilition to org1 - const memberUpdated = await MemberRepository.update( - memberCreated.id, - { - affiliations: [ - { - segmentId: segment2.id, - organizationId: org1.id, - }, - ], - }, - mockIRepositoryOptions, - ) - - expect(memberUpdated.affiliations.filter((a) => a.segmentId === segment1.id)).toHaveLength(0) - expect( - memberUpdated.affiliations.filter((a) => a.segmentId === segment2.id)[0].organizationId, - ).toEqual(org1.id) - }) - }) - - describe('destroy method', () => { - it('Should succesfully destroy previously created member', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const member1 = { - username: { - [PlatformType.DISCORD]: { - username: 'test1', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 1', - score: '1', - joinedAt: '2021-05-27T15:14:30Z', - } - const returnedMember = await MemberRepository.create(member1, mockIRepositoryOptions) - - await MemberRepository.destroy(returnedMember.id, mockIRepositoryOptions, true) - - // Try selecting it after destroy, should throw 404 - await expect(() => - MemberRepository.findById(returnedMember.id, mockIRepositoryOptions), - ).rejects.toThrowError(new Error404()) - }) - - it('Should throw 404 when trying to destroy a non existent member', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const { randomUUID } = require('crypto') - - await expect(() => - MemberRepository.destroy(randomUUID(), mockIRepositoryOptions), - ).rejects.toThrowError(new Error404()) - }) - }) - - describe('removeToMerge method', () => { - it('Should remove a member from other members toMerge list', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const member1 = { - username: { - [PlatformType.DISCORD]: { - username: 'anil', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 1', - joinedAt: '2020-05-27T15:13:30Z', - } - - const member2 = { - username: { - [PlatformType.DISCORD]: { - username: 'anil2', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 2', - joinedAt: '2020-05-27T15:13:30Z', - } - - const memberCreated1 = await MemberRepository.create(member1, mockIRepositoryOptions) - const memberCreated2 = await MemberRepository.create(member2, mockIRepositoryOptions) - - await MemberRepository.addToMerge( - [{ members: [memberCreated1.id, memberCreated2.id], similarity: null }], - mockIRepositoryOptions, - ) - await MemberRepository.addToMerge( - [{ members: [memberCreated2.id, memberCreated1.id], similarity: null }], - mockIRepositoryOptions, - ) - - let m1 = await MemberRepository.findById(memberCreated1.id, mockIRepositoryOptions) - const m2 = await MemberRepository.findById(memberCreated2.id, mockIRepositoryOptions) - m1 = await MemberRepository.removeToMerge( - memberCreated1.id, - memberCreated2.id, - mockIRepositoryOptions, - ) - - // Member2 should be removed from Member1.toMerge - expect(m1.toMerge.length).toBe(0) - - // Member1 is still in member2.toMerge list - expect(m2.toMerge[0]).toBe(m1.id) - }) - }) - - describe('addNoMerge method', () => { - it('Should add a member to other members noMerge list', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const member1 = { - username: { - [PlatformType.DISCORD]: { - username: 'anil', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 1', - joinedAt: '2020-05-27T15:13:30Z', - } - - const member2 = { - username: { - [PlatformType.DISCORD]: { - username: 'anil2', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 2', - joinedAt: '2020-05-27T15:13:30Z', - } - - const memberCreated1 = await MemberRepository.create(member1, mockIRepositoryOptions) - const memberCreated2 = await MemberRepository.create(member2, mockIRepositoryOptions) - - let memberUpdated1 = await MemberRepository.addNoMerge( - memberCreated1.id, - memberCreated2.id, - mockIRepositoryOptions, - ) - const memberUpdated2 = await MemberRepository.addNoMerge( - memberCreated2.id, - memberCreated1.id, - mockIRepositoryOptions, - ) - - memberUpdated1 = await MemberRepository.removeToMerge( - memberCreated1.id, - memberCreated2.id, - mockIRepositoryOptions, - ) - - expect(memberUpdated1.noMerge[0]).toBe(memberUpdated2.id) - expect(memberUpdated2.noMerge[0]).toBe(memberUpdated1.id) - }) - }) - - describe('removeNoMerge method', () => { - let options - let memberService - - let defaultMember - - beforeEach(async () => { - options = await SequelizeTestUtils.getTestIRepositoryOptions(db) - await populateSegments(options) - - memberService = new MemberService(options) - - defaultMember = { - platform: PlatformType.GITHUB, - joinedAt: '2020-05-27T15:13:30Z', - } - }) - it('Should remove a member from other members noMerge list', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const member1 = { - username: { - [PlatformType.DISCORD]: { - username: 'anil', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 1', - joinedAt: '2020-05-27T15:13:30Z', - } - - const member2 = { - username: { - [PlatformType.DISCORD]: { - username: 'anil2', - integrationId: generateUUIDv1(), - }, - }, - displayName: 'Member 2', - joinedAt: '2020-05-27T15:13:30Z', - } - - const memberCreated1 = await MemberRepository.create(member1, mockIRepositoryOptions) - const memberCreated2 = await MemberRepository.create(member2, mockIRepositoryOptions) - - let memberUpdated1 = await MemberRepository.addNoMerge( - memberCreated1.id, - memberCreated2.id, - mockIRepositoryOptions, - ) - const memberUpdated2 = await MemberRepository.addNoMerge( - memberCreated2.id, - memberCreated1.id, - mockIRepositoryOptions, - ) - - memberUpdated1 = await MemberRepository.removeNoMerge( - memberCreated1.id, - memberCreated2.id, - mockIRepositoryOptions, - ) - - // Member2 should be removed from Member1.noMerge - expect(memberUpdated1.noMerge.length).toBe(0) - - // Member1 is still in member2.noMerge list - expect(memberUpdated2.noMerge[0]).toBe(memberUpdated1.id) - }) - }) - - describe('work experiences', () => { - let options - let memberService - let organizationService - - let defaultMember - - beforeEach(async () => { - options = await SequelizeTestUtils.getTestIRepositoryOptions(db) - await populateSegments(options) - - memberService = new MemberService(options) - organizationService = new OrganizationService(options) - - defaultMember = { - platform: PlatformType.GITHUB, - joinedAt: '2020-05-27T15:13:30Z', - } - }) - - async function createMember(data = {}) { - return await memberService.upsert({ - ...defaultMember, - username: { - [PlatformType.GITHUB]: uuid(), - }, - ...data, - }) - } - - async function createOrg(name, data = {}) { - return await organizationService.createOrUpdate({ - identities: [ - { - name, - platform: 'crowd', - }, - ], - ...data, - }) - } - - async function addWorkExperience(memberId, orgId, data = {}) { - return await MemberRepository.createOrUpdateWorkExperience( - { - memberId, - organizationId: orgId, - source: 'test', - ...data, - }, - options, - ) - } - - async function findMember(id) { - return await memberService.findById(id) - } - - function formatDate(value) { - if (!value) { - return null - } - return moment(value).format('YYYY-MM-DD') - } - - it('Should not create multiple work experiences for same org without dates', async () => { - let member = await createMember() - - const org = await createOrg('org') - - await addWorkExperience(member.id, org.id) - await addWorkExperience(member.id, org.id) - - member = await findMember(member.id) - - expect(member.organizations.length).toBe(1) - }) - - it('Should not create multiple work experiences for same org with same start dates', async () => { - let member = await createMember() - - const org = await createOrg('org') - - await addWorkExperience(member.id, org.id, { - dateStart: '2020-01-01', - }) - await addWorkExperience(member.id, org.id, { - dateStart: '2020-01-01', - }) - - member = await findMember(member.id) - - expect(member.organizations.length).toBe(1) - }) - - it('Should not create multiple work experiences for same org with same dates', async () => { - let member = await createMember() - - const org = await createOrg('org') - - await addWorkExperience(member.id, org.id, { - dateStart: '2020-01-01', - dateEnd: '2020-01-05', - }) - await addWorkExperience(member.id, org.id, { - dateStart: '2020-01-01', - dateEnd: '2020-01-05', - }) - - member = await findMember(member.id) - - expect(member.organizations.length).toBe(1) - }) - - it('Should create multiple work experiences for same org with different dates', async () => { - let member = await createMember() - - const org = await createOrg('org') - - await addWorkExperience(member.id, org.id, { - dateStart: '2020-01-01', - }) - await addWorkExperience(member.id, org.id, { - dateStart: '2020-01-08', - }) - await addWorkExperience(member.id, org.id, { - dateStart: '2020-01-01', - dateEnd: '2020-01-05', - }) - await addWorkExperience(member.id, org.id, { - dateStart: '2020-01-06', - dateEnd: '2020-01-07', - }) - - member = await findMember(member.id) - - expect(member.organizations.length).toBe(4) - }) - - it('Should clean up work experiences without dates once we get start dates', async () => { - let member = await createMember() - - const org = await createOrg('org') - - await addWorkExperience(member.id, org.id) - await addWorkExperience(member.id, org.id, { - dateStart: '2020-01-01', - }) - - member = await findMember(member.id) - - expect(member.organizations.length).toBe(1) - const dates = member.organizations[0].memberOrganizations.dataValues - expect(formatDate(dates.dateStart)).toBe('2020-01-01') - expect(formatDate(dates.dateEnd)).toBeNull() - }) - it('Should clean up work experiences without dates once we get both dates', async () => { - let member = await createMember() - - const org = await createOrg('org') - - await addWorkExperience(member.id, org.id) - await addWorkExperience(member.id, org.id, { - dateStart: '2020-01-01', - dateEnd: '2020-07-01', - }) - - member = await findMember(member.id) - - expect(member.organizations.length).toBe(1) - const dates = member.organizations[0].memberOrganizations.dataValues - expect(formatDate(dates.dateStart)).toBe('2020-01-01') - expect(formatDate(dates.dateEnd)).toBe('2020-07-01') - }) - it('Should not add new work experiences without dates if we have start dates', async () => { - let member = await createMember() - - const org = await createOrg('org') - - await addWorkExperience(member.id, org.id, { - dateStart: '2020-01-01', - }) - await addWorkExperience(member.id, org.id) - - member = await findMember(member.id) - - expect(member.organizations.length).toBe(1) - const dates = member.organizations[0].memberOrganizations.dataValues - expect(formatDate(dates.dateStart)).toBe('2020-01-01') - expect(formatDate(dates.dateEnd)).toBeNull() - }) - it('Should not add new work experiences without dates if we have both dates', async () => { - let member = await createMember() - - const org = await createOrg('org') - - await addWorkExperience(member.id, org.id, { - dateStart: '2020-01-01', - dateEnd: '2020-07-01', - }) - await addWorkExperience(member.id, org.id) - - member = await findMember(member.id) - - expect(member.organizations.length).toBe(1) - const dates = member.organizations[0].memberOrganizations.dataValues - expect(formatDate(dates.dateStart)).toBe('2020-01-01') - expect(formatDate(dates.dateEnd)).toBe('2020-07-01') - }) - }) -}) diff --git a/backend/src/database/repositories/__tests__/organizationCacheRepository.test.ts b/backend/src/database/repositories/__tests__/organizationCacheRepository.test.ts index 09d7e88d5b..3391685fbc 100644 --- a/backend/src/database/repositories/__tests__/organizationCacheRepository.test.ts +++ b/backend/src/database/repositories/__tests__/organizationCacheRepository.test.ts @@ -82,11 +82,14 @@ describe('OrganizationCacheCacheRepository tests', () => { const expectedorganizationCacheCreated = { id: organizationCacheCreated.id, ...toCreate, + names: [toCreate.name], importHash: null, createdAt: SequelizeTestUtils.getNowWithoutTime(), updatedAt: SequelizeTestUtils.getNowWithoutTime(), deletedAt: null, } + delete expectedorganizationCacheCreated.name + expect(organizationCacheCreated).toStrictEqual(expectedorganizationCacheCreated) }) @@ -120,11 +123,13 @@ describe('OrganizationCacheCacheRepository tests', () => { const expectedorganizationCacheFound = { id: organizationCacheCreated.id, ...toCreate, + names: [toCreate.name], importHash: null, createdAt: SequelizeTestUtils.getNowWithoutTime(), updatedAt: SequelizeTestUtils.getNowWithoutTime(), deletedAt: null, } + delete expectedorganizationCacheFound.name const organizationCacheById = await organizationCacheRepository.findById( organizationCacheCreated.id, mockIRepositoryOptions, @@ -165,11 +170,13 @@ describe('OrganizationCacheCacheRepository tests', () => { const expectedorganizationCacheFound = { id: organizationCacheCreated.id, ...toCreate, + names: [toCreate.name], importHash: null, createdAt: SequelizeTestUtils.getNowWithoutTime(), updatedAt: SequelizeTestUtils.getNowWithoutTime(), deletedAt: null, } + delete expectedorganizationCacheFound.name const organizationCacheById = await organizationCacheRepository.findByUrl( organizationCacheCreated.url, mockIRepositoryOptions, @@ -200,11 +207,14 @@ describe('OrganizationCacheCacheRepository tests', () => { const expectedorganizationCacheFound = { id: organizationCacheCreated.id, ...toCreate, + names: [toCreate.name], importHash: null, createdAt: SequelizeTestUtils.getNowWithoutTime(), updatedAt: SequelizeTestUtils.getNowWithoutTime(), deletedAt: null, } + delete expectedorganizationCacheFound.name + const organizationCacheById = await organizationCacheRepository.findByUrl( organizationCacheCreated.url, mock2, @@ -228,7 +238,7 @@ describe('OrganizationCacheCacheRepository tests', () => { const organizationCacheUpdated = await organizationCacheRepository.update( organizationCacheCreated.id, - { name: 'updated-organizationCache-name' }, + { importHash: 'test' }, mockIRepositoryOptions, ) @@ -239,12 +249,13 @@ describe('OrganizationCacheCacheRepository tests', () => { const organizationCacheExpected = { id: organizationCacheCreated.id, ...toCreate, - name: organizationCacheUpdated.name, - importHash: null, + importHash: 'test', + names: [toCreate.name], createdAt: organizationCacheCreated.createdAt, updatedAt: organizationCacheUpdated.updatedAt, deletedAt: null, } + delete organizationCacheExpected.name expect(organizationCacheUpdated).toStrictEqual(organizationCacheExpected) }) diff --git a/backend/src/database/repositories/__tests__/organizationRepository.test.ts b/backend/src/database/repositories/__tests__/organizationRepository.test.ts index fa36bc6878..36a66f3c99 100644 --- a/backend/src/database/repositories/__tests__/organizationRepository.test.ts +++ b/backend/src/database/repositories/__tests__/organizationRepository.test.ts @@ -227,6 +227,7 @@ describe('OrganizationRepository tests', () => { isTeamOrganization: false, attributes: {}, weakIdentities: [], + manuallyChangedFields: null, } expect(organizationCreated).toStrictEqual(expectedOrganizationCreated) }) @@ -307,6 +308,7 @@ describe('OrganizationRepository tests', () => { isTeamOrganization: false, attributes: {}, weakIdentities: [], + manuallyChangedFields: null, } expect(organizationCreated).toStrictEqual(expectedOrganizationCreated) @@ -364,6 +366,7 @@ describe('OrganizationRepository tests', () => { isTeamOrganization: false, attributes: {}, weakIdentities: [], + manuallyChangedFields: null, } const organizationById = await OrganizationRepository.findById( organizationCreated.id, @@ -1232,6 +1235,7 @@ describe('OrganizationRepository tests', () => { isTeamOrganization: false, attributes: {}, weakIdentities: [], + manuallyChangedFields: [], } expect(organizationUpdated).toStrictEqual(organizationExpected) diff --git a/backend/src/database/repositories/__tests__/tenantRepository.test.ts b/backend/src/database/repositories/__tests__/tenantRepository.test.ts index 7e29fa2497..6d50bc8e6f 100644 --- a/backend/src/database/repositories/__tests__/tenantRepository.test.ts +++ b/backend/src/database/repositories/__tests__/tenantRepository.test.ts @@ -1,6 +1,7 @@ import TenantRepository from '../tenantRepository' import SequelizeTestUtils from '../../utils/sequelizeTestUtils' import Plans from '../../../security/plans' +import { TenantPlans } from '@crowd/types' const db = null @@ -20,12 +21,12 @@ describe('TenantRepository tests', () => { const ToCreatePLanForEssentialPlanTenantOnTrial = { name: 'essential tenant name', url: 'an-essential-tenant-name', - plan: Plans.values.essential, + plan: TenantPlans.Essential, } const ToCreatPlanForGrowthTenantOnTrial = { name: 'growth tenant name', url: 'a-growth-tenant-name', - plan: Plans.values.growth, + plan: TenantPlans.Growth, } const options = await SequelizeTestUtils.getTestIRepositoryOptions(db) await options.database.tenant.create(ToCreatePLanForEssentialPlanTenantOnTrial) @@ -36,35 +37,4 @@ describe('TenantRepository tests', () => { expect(growthTenant.id).toStrictEqual(tenantIds[0].id) }) }) - - describe('generateTenantUrl method', () => { - it('Should generate a url from name - 0 existing tenants with same url', async () => { - const options = await SequelizeTestUtils.getTestIRepositoryOptions(db) - const tenantName = 'some tenant Name with !@#_% non-alphanumeric characters' - - const generatedUrl = await TenantRepository.generateTenantUrl(tenantName, options) - const expectedGeneratedUrl = 'some-tenant-name-with-non-alphanumeric-characters' - - expect(generatedUrl).toStrictEqual(expectedGeneratedUrl) - }) - - it('Should generate a url from name - with existing tenant that has the same url', async () => { - const options = await SequelizeTestUtils.getTestIRepositoryOptions(db) - const tenantName = 'a tenant name' - - // create a tenant with url 'a-tenant-name' - await options.database.tenant.create({ - name: tenantName, - url: 'a-tenant-name', - plan: Plans.values.essential, - }) - - // now generate function should return 'a-tenant-name-1' because it already exists - const generatedUrl = await TenantRepository.generateTenantUrl(tenantName, options) - - const expectedGeneratedUrl = 'a-tenant-name-1' - - expect(generatedUrl).toStrictEqual(expectedGeneratedUrl) - }) - }) }) diff --git a/backend/src/database/repositories/activityRepository.ts b/backend/src/database/repositories/activityRepository.ts index 06e5373339..ba6263cf9e 100644 --- a/backend/src/database/repositories/activityRepository.ts +++ b/backend/src/database/repositories/activityRepository.ts @@ -1,8 +1,8 @@ import sanitizeHtml from 'sanitize-html' import lodash from 'lodash' -import Sequelize from 'sequelize' +import Sequelize, { QueryTypes } from 'sequelize' import { ActivityDisplayService } from '@crowd/integrations' -import { Error400, Error404 } from '@crowd/common' +import { Error400, Error404, RawQueryParser } from '@crowd/common' import SequelizeRepository from './sequelizeRepository' import AuditLogRepository from './auditLogRepository' import SequelizeFilterUtils from '../utils/sequelizeFilterUtils' @@ -252,7 +252,7 @@ class ActivityRepository { throw new Error404() } - return this._populateRelations(record, options) + return this._populateRelations(record, true, options) } /** @@ -275,7 +275,7 @@ class ActivityRepository { transaction, }) - return this._populateRelations(record, options) + return this._populateRelations(record, true, options) } static async filterIdInTenant(id, options: IRepositoryOptions) { @@ -322,6 +322,189 @@ class ActivityRepository { }) } + public static ACTIVITY_QUERY_FILTER_COLUMN_MAP: Map = new Map([ + ['isTeamMember', "coalesce((m.attributes -> 'isTeamMember' -> 'default')::boolean, false)"], + ['isBot', "coalesce((m.attributes -> 'isBot' -> 'default')::boolean, false)"], + ['platform', 'a.platform'], + ['type', 'a.type'], + ['channel', 'a.channel'], + ['timestamp', 'a.timestamp'], + ['memberId', 'a."memberId"'], + ['organizationId', 'a."organizationId"'], + ['conversationId', 'a."conversationId"'], + ['sentiment', 'a."sentimentMood"'], + ]) + + static async findAndCountAllv2( + { filter = {} as any, limit = 20, offset = 0, orderBy = [''], countOnly = false }, + options: IRepositoryOptions, + ) { + if (orderBy.length === 0 || (orderBy.length === 1 && orderBy[0].trim().length === 0)) { + orderBy = ['timestamp_DESC'] + } + + const tenant = SequelizeRepository.getCurrentTenant(options) + const segmentIds = SequelizeRepository.getSegmentIds(options) + const seq = SequelizeRepository.getSequelize(options) + + const params: any = { + tenantId: tenant.id, + segmentIds, + limit, + offset, + } + + if (filter.member) { + if (filter.member.isTeamMember) { + filter.isTeamMember = filter.member.isTeamMember + } + + if (filter.member.isBot) { + filter.isBot = filter.member.isBot + } + + delete filter.member + } + + const parsedOrderBys = [] + + for (const orderByPart of orderBy) { + const orderByParts = orderByPart.split('_') + const direction = orderByParts[1].toLowerCase() + switch (orderByParts[0]) { + case 'timestamp': + parsedOrderBys.push({ + property: orderByParts[0], + column: 'a.timestamp', + direction, + }) + break + case 'createdAt': + parsedOrderBys.push({ + property: orderByParts[0], + column: 'a."createdAt"', + direction, + }) + break + + default: + throw new Error(`Invalid order by: ${orderByPart}!`) + } + } + + const orderByString = parsedOrderBys.map((o) => `${o.column} ${o.direction}`).join(',') + + let filterString = RawQueryParser.parseFilters( + filter, + ActivityRepository.ACTIVITY_QUERY_FILTER_COLUMN_MAP, + [], + params, + ) + + if (filterString.trim().length === 0) { + filterString = '1=1' + } + + const baseQuery = ` + from mv_activities_cube a + inner join members m on m.id = a."memberId" + where a."tenantId" = :tenantId + and a."segmentId" in (:segmentIds) + and ${filterString} + ` + + const countQuery = ` + select count(a.id) as count + ${baseQuery} + ` + + if (countOnly) { + const countResults = (await seq.query(countQuery, { + replacements: params, + type: QueryTypes.SELECT, + })) as any + + const count = countResults[0].count + + return { + rows: [], + count, + limit, + offset, + } + } + + const query = ` + select a.id + ${baseQuery} + order by ${orderByString} + limit :limit offset :offset + ` + + const [results, countResults] = await Promise.all([ + seq.query(query, { + replacements: params, + type: QueryTypes.SELECT, + }), + seq.query(countQuery, { + replacements: params, + type: QueryTypes.SELECT, + }), + ]) + + const count = (countResults[0] as any).count + const ids = (results as any).map((r) => r.id) + + const include = [ + { + model: options.database.member, + as: 'member', + }, + { + model: options.database.activity, + as: 'parent', + include: [ + { + model: options.database.member, + as: 'member', + }, + ], + }, + { + model: options.database.member, + as: 'objectMember', + }, + { + model: options.database.organization, + as: 'organization', + }, + ] + + const order = parsedOrderBys.map((a) => [a.property, a.direction]) + + let rows = await options.database.activity.findAll({ + include, + attributes: [ + ...SequelizeFilterUtils.getLiteralProjectionsOfModel('activity', options.database), + ], + where: { + id: { + [Op.in]: ids, + }, + }, + order, + }) + + rows = await this._populateRelationsForRows(rows, false, options) + + return { + rows, + count, + limit, + offset, + } + } + static async findAndCountAll( { filter = {} as any, @@ -693,7 +876,7 @@ class ActivityRepository { transaction: SequelizeRepository.getTransaction(options), }) - rows = await this._populateRelationsForRows(rows, options) + rows = await this._populateRelationsForRows(rows, true, options) return { rows, count, limit: parsed.limit, offset: parsed.offset } } @@ -750,15 +933,15 @@ class ActivityRepository { } } - static async _populateRelationsForRows(rows, options: IRepositoryOptions) { + static async _populateRelationsForRows(rows, loadTasks: boolean, options: IRepositoryOptions) { if (!rows) { return rows } - return Promise.all(rows.map((record) => this._populateRelations(record, options))) + return Promise.all(rows.map((record) => this._populateRelations(record, loadTasks, options))) } - static async _populateRelations(record, options: IRepositoryOptions) { + static async _populateRelations(record, loadTasks: boolean, options: IRepositoryOptions) { if (!record) { return record } @@ -778,10 +961,12 @@ class ActivityRepository { ) } - output.tasks = await record.getTasks({ - transaction, - joinTableAttributes: [], - }) + if (loadTasks) { + output.tasks = await record.getTasks({ + transaction, + joinTableAttributes: [], + }) + } return output } diff --git a/backend/src/database/repositories/automationRepository.ts b/backend/src/database/repositories/automationRepository.ts index c46b549776..dacdc26557 100644 --- a/backend/src/database/repositories/automationRepository.ts +++ b/backend/src/database/repositories/automationRepository.ts @@ -3,11 +3,11 @@ import { AutomationSyncTrigger, FeatureFlag, IAutomationData, + PLAN_LIMITS, PageData, } from '@crowd/types' import Sequelize, { QueryTypes } from 'sequelize' import { Error404 } from '@crowd/common' -import { PLAN_LIMITS } from '@/feature-flags/isFeatureEnabled' import { AutomationCriteria } from '../../types/automationTypes' import { IRepositoryOptions } from './IRepositoryOptions' import AuditLogRepository from './auditLogRepository' diff --git a/backend/src/database/repositories/conversationRepository.ts b/backend/src/database/repositories/conversationRepository.ts index 5252344d75..6315b023fa 100644 --- a/backend/src/database/repositories/conversationRepository.ts +++ b/backend/src/database/repositories/conversationRepository.ts @@ -207,14 +207,29 @@ class ConversationRepository { options: IRepositoryOptions, ) { let customOrderBy: Array = [] - const include = [ + let include = [ { model: options.database.activity, as: 'activities', attributes: [], + where: {} as Record, }, ] + orderBy = 'lastActive_DESC' + + // Quick win, need to be improved. We are seeing long requests because + // filters are applied in HAVING using Sequelize, but setting these in + // WHERE clause is better for performances. + if (advancedFilter) { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + Object.entries(advancedFilter).forEach(([key, value], index) => { + if (Array.isArray(value) && value.length > 0) { + include = applyHavingInWhereClause(include, value) + } + }) + } + // If the advanced filter is empty, we construct it from the query parameter filter if (!advancedFilter) { advancedFilter = { and: [] } @@ -658,4 +673,49 @@ class ConversationRepository { } } +function applyHavingInWhereClause(include, value) { + value.forEach((constraint) => { + if (constraint.and) { + include = applyHavingInWhereClause(include, constraint.and) + } else if (constraint.or) { + include = applyHavingInWhereClause(include, constraint.or) + } + + if (constraint.lastActive) { + if (!include[0].where.timestamp) { + include[0].where.timestamp = {} + } + + if (constraint.lastActive.gte) { + include[0].where.timestamp[Op.gte] = constraint.lastActive.gte + } + if (constraint.lastActive.lte) { + include[0].where.timestamp[Op.lte] = constraint.lastActive.lte + } + if (constraint.lastActive.between) { + include[0].where.timestamp[Op.between] = constraint.lastActive.between + } + if (constraint.lastActive.not) { + if (constraint.lastActive.not.between) { + include[0].where.timestamp[Op.notBetween] = constraint.lastActive.not.between + } + } + } else if (constraint.platform) { + if (!include[0].where.platform) { + include[0].where.platform = { + [Op.in]: [], + } + } + + include[0].where.platform[Op.in].push(constraint.platform) + } else if (constraint.createdAt) { + include[0].where.createdAt = { + [Op.gte]: constraint.createdAt.gte, + } + } + }) + + return include +} + export default ConversationRepository diff --git a/backend/src/database/repositories/integrationRepository.ts b/backend/src/database/repositories/integrationRepository.ts index de882ba681..a1f5dfc44c 100644 --- a/backend/src/database/repositories/integrationRepository.ts +++ b/backend/src/database/repositories/integrationRepository.ts @@ -258,6 +258,13 @@ class IntegrationRepository { status: 'done', platform, }, + include: [ + { + model: options.database.tenant, + as: 'tenant', + required: true, + }, + ], limit: perPage, offset: (page - 1) * perPage, order: [['id', 'ASC']], diff --git a/backend/src/database/repositories/memberEnrichmentCacheRepository.ts b/backend/src/database/repositories/memberEnrichmentCacheRepository.ts index 84e9e49fdc..59a37e6471 100644 --- a/backend/src/database/repositories/memberEnrichmentCacheRepository.ts +++ b/backend/src/database/repositories/memberEnrichmentCacheRepository.ts @@ -1,5 +1,5 @@ import { QueryTypes } from 'sequelize' -import { EnrichmentCache } from '../../services/premium/enrichment/types/memberEnrichmentTypes' +import { EnrichmentCache } from '@crowd/types/premium' import { IRepositoryOptions } from './IRepositoryOptions' import SequelizeRepository from './sequelizeRepository' diff --git a/backend/src/database/repositories/memberRepository.ts b/backend/src/database/repositories/memberRepository.ts index 6a31d8b7d2..56329a53bd 100644 --- a/backend/src/database/repositories/memberRepository.ts +++ b/backend/src/database/repositories/memberRepository.ts @@ -47,7 +47,7 @@ import { } from './types/memberTypes' import OrganizationRepository from './organizationRepository' import MemberSyncRemoteRepository from './memberSyncRemoteRepository' -import MemberAffiliationRepository from './memberAffiliationRepository' +import MemberAttributeSettingsRepository from './memberAttributeSettingsRepository' const { Op } = Sequelize @@ -238,42 +238,46 @@ class MemberRepository { } static async findMembersWithMergeSuggestions( - { limit = 20, offset = 0 }, + { limit = 20, offset = 0, memberId = undefined }, options: IRepositoryOptions, ) { - const currentTenant = SequelizeRepository.getCurrentTenant(options) const segmentIds = SequelizeRepository.getSegmentIds(options) + const isSegmentsEnabled = await isFeatureEnabled(FeatureFlag.SEGMENTS, options) + + const order = isSegmentsEnabled + ? 'mtm."activityEstimate" desc, mtm.similarity desc, mtm."memberId", mtm."toMergeId"' + : 'mtm.similarity desc, mtm."activityEstimate" desc, mtm."memberId", mtm."toMergeId"' + + const similarityFilter = isSegmentsEnabled ? ' and mtm.similarity > 0.95 ' : '' + + const memberFilter = memberId + ? ` and (mtm."memberId" = :memberId OR mtm."toMergeId" = :memberId)` + : '' + const mems = await options.database.sequelize.query( - `SELECT - "membersToMerge".id, - "membersToMerge"."toMergeId", - "membersToMerge"."total_count", - "membersToMerge"."similarity" - FROM - ( - SELECT DISTINCT ON (Greatest(Hashtext(Concat(mem.id, mtm."toMergeId")), Hashtext(Concat(mtm."toMergeId", mem.id)))) - mem.id, - mtm."toMergeId", - mem."joinedAt", - COUNT(*) OVER() AS total_count, - mtm."similarity" - FROM members mem - INNER JOIN "memberToMerge" mtm ON mem.id = mtm."memberId" - JOIN "memberSegments" ms ON ms."memberId" = mem.id - WHERE mem."tenantId" = :tenantId - AND ms."segmentId" IN (:segmentIds) - ) AS "membersToMerge" - ORDER BY - "membersToMerge"."similarity" DESC - LIMIT :limit OFFSET :offset - `, + ` + SELECT + DISTINCT + mtm."memberId" AS id, + mtm."toMergeId", + mtm.similarity, + mtm."activityEstimate" + FROM "memberToMerge" mtm + JOIN member_segments_mv ms ON ms."memberId" = mtm."memberId" + WHERE ms."segmentId" IN (:segmentIds) + ${memberFilter} + ${similarityFilter} + ORDER BY ${order} + LIMIT :limit + OFFSET :offset + `, { replacements: { - tenantId: currentTenant.id, segmentIds, limit, offset, + memberId, }, type: QueryTypes.SELECT, }, @@ -295,7 +299,27 @@ class MemberRepository { members: [i, memberToMergeResults[idx]], similarity: mems[idx].similarity, })) - return { rows: result, count: mems[0].total_count / 2, limit, offset } + + const totalCount = await options.database.sequelize.query( + ` + SELECT + COUNT(DISTINCT mtm."memberId"::TEXT || mtm."toMergeId"::TEXT) AS count + FROM "memberToMerge" mtm + JOIN member_segments_mv ms ON ms."memberId" = mtm."memberId" + WHERE ms."segmentId" IN (:segmentIds) + ${memberFilter} + ${similarityFilter} + `, + { + replacements: { + segmentIds, + memberId, + }, + type: QueryTypes.SELECT, + }, + ) + + return { rows: result, count: totalCount[0].count, limit, offset } } return { rows: [{ members: [], similarity: 0 }], count: 0, limit, offset } @@ -344,32 +368,6 @@ class MemberRepository { } } - static async moveActivitiesBetweenMembers( - fromMemberId: string, - toMemberId: string, - options: IRepositoryOptions, - ): Promise { - const transaction = SequelizeRepository.getTransaction(options) - - const seq = SequelizeRepository.getSequelize(options) - - const tenant = SequelizeRepository.getCurrentTenant(options) - - const query = ` - update activities set "memberId" = :toMemberId where "memberId" = :fromMemberId and "tenantId" = :tenantId; - ` - - await seq.query(query, { - replacements: { - fromMemberId, - toMemberId, - tenantId: tenant.id, - }, - type: QueryTypes.UPDATE, - transaction, - }) - } - static async addToMerge( suggestions: IMemberMergeSuggestion[], options: IRepositoryOptions, @@ -421,7 +419,7 @@ class MemberRepository { const query = ` INSERT INTO "memberToMerge" ("memberId", "toMergeId", "similarity", "createdAt", "updatedAt") - VALUES ${placeholders.join(', ')}; + VALUES ${placeholders.join(', ')} on conflict do nothing; ` try { await seq.query(query, { @@ -968,7 +966,6 @@ class MemberRepository { ): Promise { const affiliationRepository = new MemberSegmentAffiliationRepository(options) await affiliationRepository.setForMember(memberId, data) - await MemberAffiliationRepository.update(memberId, options) } static async getAffiliations( @@ -1166,6 +1163,96 @@ class MemberRepository { }) } + static async findByIdOpensearch(id, options: IRepositoryOptions, segmentId?: string) { + const segments = segmentId ? [segmentId] : SequelizeRepository.getSegmentIds(options) + + const memberAttributeSettings = ( + await MemberAttributeSettingsRepository.findAndCountAll({}, options) + ).rows + + const response = await this.findAndCountAllOpensearch( + { + filter: { + and: [ + { + id: { + eq: id, + }, + }, + ], + }, + limit: 1, + offset: 0, + attributesSettings: memberAttributeSettings, + segments, + }, + options, + ) + + if (response.count === 0) { + throw new Error404() + } + + const result = response.rows[0] + + // Get special attributes from memberAttributeSettings + const specialAttributes = memberAttributeSettings + .filter((setting) => setting.type === 'special') + .map((setting) => setting.name) + + // Parse special attributes that are indexed as strings + if (result.attributes) { + specialAttributes.forEach((attr) => { + if (result.attributes[attr]) { + result.attributes[attr] = JSON.parse(result.attributes[attr]) + } + }) + } + + // Sort the organizations based on dateStart + if (result.organizations) { + result.organizations.sort((a, b) => { + const dateStartA = a.memberOrganizations.dateStart + const dateStartB = b.memberOrganizations.dateStart + + if (!dateStartA && !dateStartB) { + return 0 + } + + if (!dateStartA) { + return 1 + } + + if (!dateStartB) { + return -1 + } + + return new Date(dateStartB).getTime() - new Date(dateStartA).getTime() + }) + } + + const seq = SequelizeRepository.getSequelize(options) + result.segments = await seq.query( + ` + SELECT + s.id, + s.name + FROM mv_activities_cube a + JOIN segments s ON s.id = a."segmentId" + WHERE a."memberId" = :id + GROUP BY s.id + `, + { + replacements: { + id, + }, + type: QueryTypes.SELECT, + }, + ) + + return result + } + static async findAndCountActiveOpensearch( filter: IActiveMemberFilter, limit: number, @@ -1405,6 +1492,20 @@ class MemberRepository { }) } + if (filter.isDeleted === true) { + memberQueryPayload.and.push({ + isDeleted: { + eq: true, + }, + }) + } else if (filter.isDeleted === false) { + memberQueryPayload.and.push({ + isDeleted: { + not: true, + }, + }) + } + // to retain the sort came from activity query const customSortFunction = { _script: { @@ -1632,6 +1733,7 @@ class MemberRepository { ['isOrganization', "coalesce((m.attributes -> 'isOrganization' -> 'default')::boolean, false)"], ['isTeamMember', "coalesce((m.attributes -> 'isTeamMember' -> 'default')::boolean, false)"], ['isBot', "coalesce((m.attributes -> 'isBot' -> 'default')::boolean, false)"], + ['isDeleted', "coalesce((m.attributes -> 'isDeleted' -> 'default')::boolean, false)"], ['activeOn', 'aggs."activeOn"'], ['activityCount', 'aggs."activityCount"'], ['activityTypes', 'aggs."activityTypes"'], @@ -2075,6 +2177,16 @@ class MemberRepository { }, }) + // remove deleted members + if (!parsed.query.bool.must_not) { + parsed.query.bool.must_not = [] + } + parsed.query.bool.must_not.push({ + term: { + 'obj_attributes.obj_isDeleted.bool_default': true, + }, + }) + if (segmentsEnabled) { // add segment filter parsed.query.bool.must.push({ @@ -2169,27 +2281,27 @@ class MemberRepository { const memberIds = translatedRows.map((r) => r.id) if (memberIds.length > 0) { const seq = SequelizeRepository.getSequelize(options) - const segmentIds = segments const lastActivities = await seq.query( ` - WITH - raw_data AS ( - SELECT *, ROW_NUMBER() OVER (PARTITION BY "memberId" ORDER BY timestamp DESC) AS rn - FROM activities - WHERE "tenantId" = :tenantId - AND "memberId" IN (:memberIds) - AND "segmentId" IN (:segmentIds) - ) - SELECT * - FROM raw_data - WHERE rn = 1; + SELECT + a.* + FROM ( + VALUES + ${memberIds.map((id) => `('${id}')`).join(',')} + ) m ("memberId") + JOIN activities a ON (a.id = ( + SELECT id + FROM mv_activities_cube + WHERE "memberId" = m."memberId"::uuid + ORDER BY timestamp DESC + LIMIT 1 + )) + WHERE a."tenantId" = :tenantId `, { replacements: { tenantId: tenant.id, - segmentIds, - memberIds, }, type: QueryTypes.SELECT, }, @@ -3401,15 +3513,7 @@ class MemberRepository { } static async createOrUpdateWorkExperience( - { - memberId, - organizationId, - source, - title = null, - dateStart = null, - dateEnd = null, - updateAffiliation = true, - }, + { memberId, organizationId, source, title = null, dateStart = null, dateEnd = null }, options: IRepositoryOptions, ) { const seq = SequelizeRepository.getSequelize(options) @@ -3492,10 +3596,6 @@ class MemberRepository { transaction, }, ) - - if (updateAffiliation) { - await MemberAffiliationRepository.update(memberId, options) - } } static async deleteWorkExperience(id, options: IRepositoryOptions) { diff --git a/backend/src/database/repositories/mergeActionsRepository.ts b/backend/src/database/repositories/mergeActionsRepository.ts index 9913ccd154..6c45f9c053 100644 --- a/backend/src/database/repositories/mergeActionsRepository.ts +++ b/backend/src/database/repositories/mergeActionsRepository.ts @@ -11,6 +11,7 @@ enum MergeActionState { PENDING = 'pending', IN_PROGRESS = 'in-progress', DONE = 'done', + FINISHING = 'finishing', ERROR = 'error', } diff --git a/backend/src/database/repositories/organizationCacheRepository.ts b/backend/src/database/repositories/organizationCacheRepository.ts index a85b6998c7..ae5ac4c36f 100644 --- a/backend/src/database/repositories/organizationCacheRepository.ts +++ b/backend/src/database/repositories/organizationCacheRepository.ts @@ -1,17 +1,43 @@ -import lodash from 'lodash' import { Error404 } from '@crowd/common' -import SequelizeRepository from './sequelizeRepository' -import AuditLogRepository from './auditLogRepository' +import lodash from 'lodash' +import { QueryTypes } from 'sequelize' import { IRepositoryOptions } from './IRepositoryOptions' +import AuditLogRepository from './auditLogRepository' +import SequelizeRepository from './sequelizeRepository' class OrganizationCacheRepository { + static async linkCacheAndOrganization( + cacheId: string, + organizationId: string, + options: IRepositoryOptions, + ): Promise { + const transaction = SequelizeRepository.getTransaction(options) + const seq = SequelizeRepository.getSequelize(options) + + await seq.query( + ` + insert into "organizationCacheLinks"("organizationCacheId", "organizationId") + values (:cacheId, :organizationId) + on conflict do nothing; + `, + { + replacements: { + cacheId, + organizationId, + }, + transaction, + type: QueryTypes.INSERT, + }, + ) + } + static async create(data, options: IRepositoryOptions) { const transaction = SequelizeRepository.getTransaction(options) + const seq = SequelizeRepository.getSequelize(options) const record = await options.database.organizationCache.create( { ...lodash.pick(data, [ - 'name', 'url', 'description', 'emails', @@ -25,7 +51,6 @@ class OrganizationCacheRepository { 'revenueRange', 'importHash', 'enriched', - 'website', 'github', 'location', 'employeeCountByCountry', @@ -47,13 +72,33 @@ class OrganizationCacheRepository { }, ) + await seq.query( + ` + insert into "organizationCacheIdentities"(id, name, website) values(:id, :name, :website) + on conflict (name) + do update + set website = coalesce("organizationCacheIdentities".website, EXCLUDED.website) + where "organizationCacheIdentities".website is null; + `, + { + replacements: { + id: record.id, + name: data.name, + website: data.website || null, + }, + type: QueryTypes.INSERT, + transaction, + }, + ) + await this._createAuditLog(AuditLogRepository.CREATE, record, data, options) return this.findById(record.id, options) } - static async update(id, data, options: IRepositoryOptions) { + static async update(id, data, options: IRepositoryOptions, nameToCreateIdentity?: string) { const transaction = SequelizeRepository.getTransaction(options) + const seq = SequelizeRepository.getSequelize(options) let record = await options.database.organizationCache.findOne({ where: { @@ -69,7 +114,6 @@ class OrganizationCacheRepository { record = await record.update( { ...lodash.pick(data, [ - 'name', 'url', 'description', 'emails', @@ -83,7 +127,6 @@ class OrganizationCacheRepository { 'revenueRange', 'importHash', 'enriched', - 'website', 'github', 'location', 'geoLocation', @@ -112,6 +155,41 @@ class OrganizationCacheRepository { throw new Error404() } + if (nameToCreateIdentity) { + await seq.query( + ` + insert into "organizationCacheIdentities" (id, name, website) values (:id, :name, :website) + on conflict (name) + do update + set website = coalesce("organizationCacheIdentities".website, EXCLUDED.website) + where "organizationCacheIdentities".website is null; + `, + { + replacements: { + id, + name: nameToCreateIdentity, + website: data.website || null, + }, + type: QueryTypes.INSERT, + transaction, + }, + ) + } + + if (data.website) { + await seq.query( + `update "organizationCacheIdentities" set website = :website where id = :id and website is null`, + { + replacements: { + id, + website: data.website, + }, + type: QueryTypes.UPDATE, + transaction, + }, + ) + } + await this._createAuditLog(AuditLogRepository.UPDATE, record, data, options) return this.findById(record.id, options) @@ -153,6 +231,7 @@ class OrganizationCacheRepository { static async destroy(id, options: IRepositoryOptions, force = false) { const transaction = SequelizeRepository.getTransaction(options) + const seq = SequelizeRepository.getSequelize(options) const record = await options.database.organizationCache.findOne({ where: { @@ -165,6 +244,14 @@ class OrganizationCacheRepository { throw new Error404() } + await seq.query('delete from "organizationCacheIdentities" where id = :id', { + replacements: { + id, + type: QueryTypes.DELETE, + transaction, + }, + }) + await record.destroy({ transaction, force, @@ -175,6 +262,7 @@ class OrganizationCacheRepository { static async findById(id, options: IRepositoryOptions) { const transaction = SequelizeRepository.getTransaction(options) + const seq = SequelizeRepository.getSequelize(options) const include = [] @@ -189,7 +277,32 @@ class OrganizationCacheRepository { if (!record) { throw new Error404() } - const output = record.get({ plain: true }) + + const identityRows = await seq.query( + `select name, website from "organizationCacheIdentities" where id = :id`, + { + replacements: { + id, + }, + type: QueryTypes.SELECT, + transaction, + }, + ) + + const names = (identityRows as any[]).map((r) => r.name) + // we just need one website since every identity should have the same website for the same organization cache + const website = (identityRows as any[]) + .filter((r) => r.website !== null) + .map((r) => r.website) + .reduce((prev, curr) => { + if (prev === null) { + return curr + } + + return prev + }, null) + + const output = { ...record.get({ plain: true }), names, website } return output } @@ -204,35 +317,60 @@ class OrganizationCacheRepository { }, include, transaction, + attributes: ['id'], }) if (!record) { return undefined } - const output = record.get({ plain: true }) - return output + return this.findById(record.id, options) } - static async findByName(name, options: IRepositoryOptions) { + static async findByWebsite(website: string, options: IRepositoryOptions) { const transaction = SequelizeRepository.getTransaction(options) - const include = [] + const seq = SequelizeRepository.getSequelize(options) - const record = await options.database.organizationCache.findOne({ - where: { - name, + const result = await seq.query( + `select id from "organizationCacheIdentities" where website = :website`, + { + replacements: { + website, + }, + type: QueryTypes.SELECT, + transaction, }, - include, - transaction, - }) + ) - if (!record) { - return undefined + if (result.length === 1) { + return this.findById((result[0] as any).id, options) } - const output = record.get({ plain: true }) - return output + return undefined + } + + static async findByName(name: string, options: IRepositoryOptions) { + const transaction = SequelizeRepository.getTransaction(options) + + const seq = SequelizeRepository.getSequelize(options) + + const result = await seq.query( + `select id from "organizationCacheIdentities" where name = :name`, + { + replacements: { + name, + }, + type: QueryTypes.SELECT, + transaction, + }, + ) + + if (result.length === 1) { + return this.findById((result[0] as any).id, options) + } + + return undefined } static async _createAuditLog(action, record, data, options: IRepositoryOptions) { diff --git a/backend/src/database/repositories/organizationRepository.ts b/backend/src/database/repositories/organizationRepository.ts index ad478a345f..73ac9e7fd2 100644 --- a/backend/src/database/repositories/organizationRepository.ts +++ b/backend/src/database/repositories/organizationRepository.ts @@ -2,7 +2,7 @@ import lodash, { chunk } from 'lodash' import { get as getLevenshteinDistance } from 'fast-levenshtein' import validator from 'validator' import { FieldTranslatorFactory, OpensearchQueryParser } from '@crowd/opensearch' -import { Error404, PageData } from '@crowd/common' +import { Error400, Error404, Error409, PageData } from '@crowd/common' import { FeatureFlag, IEnrichableOrganization, @@ -11,6 +11,8 @@ import { IOrganizationMergeSuggestion, OpenSearchIndex, SegmentData, + SegmentProjectGroupNestedData, + SegmentProjectNestedData, SyncStatus, } from '@crowd/types' import Sequelize, { QueryTypes } from 'sequelize' @@ -24,6 +26,7 @@ import OrganizationSyncRemoteRepository from './organizationSyncRemoteRepository import isFeatureEnabled from '@/feature-flags/isFeatureEnabled' import SegmentRepository from './segmentRepository' import { MergeActionType, MergeActionState } from './mergeActionsRepository' +import { IActiveOrganizationData, IActiveOrganizationFilter } from './types/organizationTypes' const { Op } = Sequelize @@ -40,6 +43,7 @@ interface IOrganizationPartialAggregatesOpensearch { string_name: string }[] uuid_arr_noMergeIds: string[] + keyword_displayName: string } } @@ -49,6 +53,7 @@ interface ISimilarOrganization { uuid_organizationId: string nested_identities: IOrganizationIdentityOpensearch[] nested_weakIdentities: IOrganizationIdentityOpensearch[] + keyword_displayName: string } } @@ -517,7 +522,64 @@ class OrganizationRepository { }) } - static async update(id, data, options: IRepositoryOptions, overrideIdentities = false) { + static ORGANIZATION_UPDATE_COLUMNS = [ + 'displayName', + 'description', + 'emails', + 'phoneNumbers', + 'logo', + 'tags', + 'website', + 'location', + 'github', + 'twitter', + 'linkedin', + 'crunchbase', + 'employees', + 'revenueRange', + 'importHash', + 'isTeamOrganization', + 'employeeCountByCountry', + 'type', + 'ticker', + 'headline', + 'profiles', + 'naics', + 'industry', + 'founded', + 'size', + 'employees', + 'twitter', + 'lastEnrichedAt', + 'affiliatedProfiles', + 'allSubsidiaries', + 'alternativeDomains', + 'alternativeNames', + 'averageEmployeeTenure', + 'averageTenureByLevel', + 'averageTenureByRole', + 'directSubsidiaries', + 'employeeChurnRate', + 'employeeCountByMonth', + 'employeeGrowthRate', + 'employeeCountByMonthByLevel', + 'employeeCountByMonthByRole', + 'gicsSector', + 'grossAdditionsByMonth', + 'grossDeparturesByMonth', + 'ultimateParent', + 'immediateParent', + 'attributes', + 'weakIdentities', + ] + + static async update( + id, + data, + options: IRepositoryOptions, + overrideIdentities = false, + manualChange = false, + ) { const currentUser = SequelizeRepository.getCurrentUser(options) const transaction = SequelizeRepository.getTransaction(options) @@ -536,64 +598,77 @@ class OrganizationRepository { throw new Error404() } + // check if website already exists in another organization in the same tenant + if (data.website) { + const existingOrg = await options.database.organization.findOne({ + where: { + website: data.website, + tenantId: currentTenant.id, + }, + transaction, + }) + + // ensure that it's not the same organization + if (existingOrg && existingOrg.id !== record.id) { + throw new Error409(options.language, 'organization.errors.websiteAlreadyExists') + } + } + // exclude syncRemote attributes, since these are populated from organizationSyncRemote table if (data.attributes?.syncRemote) { delete data.attributes.syncRemote } + if (manualChange) { + const manuallyChangedFields: string[] = record.manuallyChangedFields || [] + + for (const column of this.ORGANIZATION_UPDATE_COLUMNS) { + let changed = false + + // only check fields that are in the data object that will be updated + if (column in data) { + if ( + record[column] !== null && + column in data && + (data[column] === null || data[column] === undefined) + ) { + // column was removed in the update -> will be set to null by sequelize + changed = true + } else if ( + record[column] === null && + data[column] !== null && + data[column] !== undefined + ) { + // column was null before now it's not anymore + changed = true + } else if (record[column] !== data[column]) { + // column value has changed + changed = true + } + } + + if (changed && !manuallyChangedFields.includes(column)) { + manuallyChangedFields.push(column) + } + } + + data.manuallyChangedFields = manuallyChangedFields + } else { + // ignore columns that were manually changed + // by rewriting them with db data + const manuallyChangedFields: string[] = record.manuallyChangedFields || [] + for (const manuallyChangedColumn of manuallyChangedFields) { + data[manuallyChangedColumn] = record[manuallyChangedColumn] + } + + data.manuallyChangedFields = manuallyChangedFields + } + record = await record.update( { - ...lodash.pick(data, [ - 'displayName', - 'description', - 'emails', - 'phoneNumbers', - 'logo', - 'tags', - 'website', - 'location', - 'github', - 'twitter', - 'linkedin', - 'crunchbase', - 'employees', - 'revenueRange', - 'importHash', - 'isTeamOrganization', - 'employeeCountByCountry', - 'type', - 'ticker', - 'headline', - 'profiles', - 'naics', - 'industry', - 'founded', - 'size', - 'employees', - 'twitter', - 'lastEnrichedAt', - 'affiliatedProfiles', - 'allSubsidiaries', - 'alternativeDomains', - 'alternativeNames', - 'averageEmployeeTenure', - 'averageTenureByLevel', - 'averageTenureByRole', - 'directSubsidiaries', - 'employeeChurnRate', - 'employeeCountByMonth', - 'employeeGrowthRate', - 'employeeCountByMonthByLevel', - 'employeeCountByMonthByRole', - 'gicsSector', - 'grossAdditionsByMonth', - 'grossDeparturesByMonth', - 'ultimateParent', - 'immediateParent', - 'attributes', - 'weakIdentities', - ]), + ...lodash.pick(data, this.ORGANIZATION_UPDATE_COLUMNS), updatedById: currentUser.id, + manuallyChangedFields: data.manuallyChangedFields, }, { transaction, @@ -1062,50 +1137,6 @@ class OrganizationRepository { } } - static async moveActivitiesBetweenOrganizations( - fromOrganizationId: string, - toOrganizationId: string, - options: IRepositoryOptions, - batchSize = 10000, - ): Promise { - const transaction = SequelizeRepository.getTransaction(options) - const seq = SequelizeRepository.getSequelize(options) - const tenant = SequelizeRepository.getCurrentTenant(options) - - let updatedRowsCount = 0 - - do { - options.log.info( - `[Move Activities] - Moving maximum of ${batchSize} activities from ${fromOrganizationId} to ${toOrganizationId}.`, - ) - - const query = ` - UPDATE "activities" - SET "organizationId" = :newOrganizationId - WHERE id IN ( - SELECT id - FROM "activities" - WHERE "tenantId" = :tenantId - AND "organizationId" = :oldOrganizationId - LIMIT :limit - ) - ` - - const [, rowCount] = await seq.query(query, { - replacements: { - tenantId: tenant.id, - oldOrganizationId: fromOrganizationId, - newOrganizationId: toOrganizationId, - limit: batchSize, - }, - type: QueryTypes.UPDATE, - transaction, - }) - - updatedRowsCount = rowCount ?? 0 - } while (updatedRowsCount === batchSize) - } - static async *getMergeSuggestions( options: IRepositoryOptions, ): AsyncGenerator { @@ -1135,6 +1166,7 @@ class OrganizationRepository { for (const primaryIdentity of primaryOrganization._source.nested_identities) { // similar organization has a weakIdentity as one of primary organization's strong identity, return score 95 if ( + similarOrganization._source.nested_weakIdentities && similarOrganization._source.nested_weakIdentities.length > 0 && similarOrganization._source.nested_weakIdentities.some( (weakIdentity) => @@ -1144,6 +1176,15 @@ class OrganizationRepository { ) { return 0.95 } + + // check displayName match + if ( + similarOrganization._source.keyword_displayName === + primaryOrganization._source.keyword_displayName + ) { + return 0.98 + } + for (const secondaryIdentity of similarOrganization._source.nested_identities) { const currentLevenstheinDistance = getLevenshteinDistance( primaryIdentity.string_name, @@ -1179,7 +1220,12 @@ class OrganizationRepository { collapse: { field: 'uuid_organizationId', }, - _source: ['uuid_organizationId', 'nested_identities', 'uuid_arr_noMergeIds'], + _source: [ + 'uuid_organizationId', + 'nested_identities', + 'uuid_arr_noMergeIds', + 'keyword_displayName', + ], } let organizations: IOrganizationPartialAggregatesOpensearch[] = [] @@ -1190,25 +1236,6 @@ class OrganizationRepository { queryBody.query = { bool: { filter: [ - { - bool: { - should: [ - { - range: { - int_activityCount: { - gt: 0, - }, - }, - }, - { - term: { - bool_manuallyCreated: true, - }, - }, - ], - minimum_should_match: 1, - }, - }, { term: { uuid_tenantId: tenant.id, @@ -1228,25 +1255,6 @@ class OrganizationRepository { queryBody.query = { bool: { filter: [ - { - bool: { - should: [ - { - range: { - int_activityCount: { - gt: 0, - }, - }, - }, - { - term: { - bool_manuallyCreated: true, - }, - }, - ], - minimum_should_match: 1, - }, - }, { term: { uuid_tenantId: tenant.id, @@ -1276,6 +1284,11 @@ class OrganizationRepository { ) { const identitiesPartialQuery = { should: [ + { + term: { + [`keyword_displayName`]: organization._source.keyword_displayName, + }, + }, { nested: { path: 'nested_weakIdentities', @@ -1315,25 +1328,6 @@ class OrganizationRepository { uuid_tenantId: tenant.id, }, }, - { - bool: { - should: [ - { - range: { - int_activityCount: { - gt: 0, - }, - }, - }, - { - term: { - bool_manuallyCreated: true, - }, - }, - ], - minimum_should_match: 1, - }, - }, ], } @@ -1342,7 +1336,7 @@ class OrganizationRepository { for (const identity of organization._source.nested_identities) { if (identity.string_name.length > 0) { // weak identity search - identitiesPartialQuery.should[0].nested.query.bool.should.push({ + identitiesPartialQuery.should[1].nested.query.bool.should.push({ bool: { must: [ { match: { [`nested_weakIdentities.keyword_name`]: identity.string_name } }, @@ -1363,7 +1357,7 @@ class OrganizationRepository { if (Number.isNaN(Number(identity.string_name))) { hasFuzzySearch = true // fuzzy search for identities - identitiesPartialQuery.should[1].nested.query.bool.should.push({ + identitiesPartialQuery.should[2].nested.query.bool.should.push({ match: { [`nested_identities.keyword_name`]: { query: cleanedIdentityName, @@ -1375,7 +1369,7 @@ class OrganizationRepository { // also check for prefix for identities that has more than 5 characters and no whitespace if (identity.string_name.length > 5 && identity.string_name.indexOf(' ') === -1) { - identitiesPartialQuery.should[1].nested.query.bool.should.push({ + identitiesPartialQuery.should[2].nested.query.bool.should.push({ prefix: { [`nested_identities.keyword_name`]: { value: cleanedIdentityName.slice(0, prefixLength(cleanedIdentityName)), @@ -1414,7 +1408,12 @@ class OrganizationRepository { collapse: { field: 'uuid_organizationId', }, - _source: ['uuid_organizationId', 'nested_identities', 'nested_weakIdentities'], + _source: [ + 'uuid_organizationId', + 'nested_identities', + 'nested_weakIdentities', + 'keyword_displayName', + ], } const organizationsToMerge: ISimilarOrganization[] = @@ -1449,12 +1448,16 @@ class OrganizationRepository { } static async findOrganizationsWithMergeSuggestions( - { limit = 20, offset = 0 }, + { limit = 20, offset = 0, organizationId = undefined }, options: IRepositoryOptions, ) { const currentTenant = SequelizeRepository.getCurrentTenant(options) const segmentIds = SequelizeRepository.getSegmentIds(options) + const organizationFilter = organizationId + ? ` AND ("otm"."organizationId" = :organizationId OR "otm"."toMergeId" = :organizationId)` + : '' + const orgs = await options.database.sequelize.query( `WITH cte AS ( @@ -1477,6 +1480,7 @@ class OrganizationRepository { WHERE org."tenantId" = :tenantId AND os."segmentId" IN (:segmentIds) AND (ma.id IS NULL OR ma.state = :mergeActionStatus) + ${organizationFilter} ), count_cte AS ( @@ -1514,6 +1518,7 @@ class OrganizationRepository { offset, mergeActionType: MergeActionType.ORG, mergeActionStatus: MergeActionState.ERROR, + organizationId, }, type: QueryTypes.SELECT, }, @@ -1570,6 +1575,87 @@ class OrganizationRepository { return segments } + static async findByIdentities( + identities: IOrganizationIdentity[], + options: IRepositoryOptions, + ): Promise { + const transaction = SequelizeRepository.getTransaction(options) + const sequelize = SequelizeRepository.getSequelize(options) + const currentTenant = SequelizeRepository.getCurrentTenant(options) + + const identityConditions = identities + .map( + (identity, index) => ` + (oi.platform = :platform${index} and oi.name = :name${index}) + `, + ) + .join(' or ') + + const results = await sequelize.query( + ` + with + "organizationsWithIdentity" as ( + select oi."organizationId" + from "organizationIdentities" oi + where ${identityConditions} + ), + "organizationsWithCounts" as ( + select o.id, count(oi."organizationId") as total_counts + from organizations o + join "organizationIdentities" oi on o.id = oi."organizationId" + where o.id in (select "organizationId" from "organizationsWithIdentity") + group by o.id + ) + select o.id, + o.description, + o.emails, + o.logo, + o.tags, + o.github, + o.twitter, + o.linkedin, + o.crunchbase, + o.employees, + o.location, + o.website, + o.type, + o.size, + o.headline, + o.industry, + o.founded, + o.attributes + from organizations o + inner join "organizationsWithCounts" oc on o.id = oc.id + where o."tenantId" = :tenantId + order by oc.total_counts desc + limit 1; + `, + { + replacements: { + tenantId: currentTenant.id, + ...identities.reduce( + (acc, identity, index) => ({ + ...acc, + [`platform${index}`]: identity.platform, + [`name${index}`]: identity.name, + }), + {}, + ), + }, + type: QueryTypes.SELECT, + transaction, + }, + ) + + if (results.length === 0) { + return null + } + + const result = results[0] as IOrganization + + return result + } + static async findByIdentity( identity: IOrganizationIdentity, options: IRepositoryOptions, @@ -2039,6 +2125,46 @@ class OrganizationRepository { return results } + static async findByIdOpensearch( + id: string, + options: IRepositoryOptions, + segmentId?: string, + ): Promise> { + const segments = segmentId ? [segmentId] : SequelizeRepository.getSegmentIds(options) + + const response = await this.findAndCountAllOpensearch( + { + filter: { + and: [ + { + id: { + eq: id, + }, + }, + ], + }, + isProfileQuery: true, + limit: 1, + offset: 0, + segments, + }, + options, + ) + + if (response.count === 0) { + throw new Error404() + } + + const result = response.rows[0] + + // Parse attributes that are indexed as strings + if (result.attributes) { + result.attributes = JSON.parse(result.attributes) + } + + return result + } + static async findAndCountAllOpensearch( { filter = {} as any, @@ -2048,6 +2174,7 @@ class OrganizationRepository { countOnly = false, segments = [] as string[], customSortFunction = undefined, + isProfileQuery = false, }, options: IRepositoryOptions, ): Promise> { @@ -2063,7 +2190,7 @@ class OrganizationRepository { const translator = FieldTranslatorFactory.getTranslator(OpenSearchIndex.ORGANIZATIONS) - if (filter.and) { + if (!isProfileQuery && filter.and) { filter.and.push({ or: [ { @@ -2141,6 +2268,250 @@ class OrganizationRepository { return { rows: translatedRows, count: countResponse.body.count, limit, offset } } + static async findAndCountActiveOpensearch( + filter: IActiveOrganizationFilter, + limit: number, + offset: number, + orderBy: string, + options: IRepositoryOptions, + segments: string[] = [], + ): Promise> { + const tenant = SequelizeRepository.getCurrentTenant(options) + + const segmentsEnabled = await isFeatureEnabled(FeatureFlag.SEGMENTS, options) + + let originalSegment + + if (segmentsEnabled) { + if (segments.length !== 1) { + throw new Error400( + `This operation can have exactly one segment. Found ${segments.length} segments.`, + ) + } + originalSegment = segments[0] + + const segmentRepository = new SegmentRepository(options) + + const segment = await segmentRepository.findById(originalSegment) + + if (segment === null) { + return { + rows: [], + count: 0, + limit, + offset, + } + } + + if (SegmentRepository.isProjectGroup(segment)) { + segments = (segment as SegmentProjectGroupNestedData).projects.reduce((acc, p) => { + acc.push(...p.subprojects.map((sp) => sp.id)) + return acc + }, []) + } else if (SegmentRepository.isProject(segment)) { + segments = (segment as SegmentProjectNestedData).subprojects.map((sp) => sp.id) + } else { + segments = [originalSegment] + } + } else { + originalSegment = (await new SegmentRepository(options).getDefaultSegment()).id + } + + const activityPageSize = 10000 + let activityOffset = 0 + + const activityQuery = { + query: { + bool: { + must: [ + { + range: { + date_timestamp: { + gte: filter.activityTimestampFrom, + lte: filter.activityTimestampTo, + }, + }, + }, + { + term: { + uuid_tenantId: tenant.id, + }, + }, + ], + }, + }, + aggs: { + group_by_organization: { + terms: { + field: 'uuid_organizationId', + size: 10000000, + }, + aggs: { + activity_count: { + value_count: { + field: 'uuid_id', + }, + }, + active_days_count: { + cardinality: { + field: 'date_timestamp', + script: { + source: "doc['date_timestamp'].value.toInstant().toEpochMilli()/86400000", + }, + }, + }, + active_organizations_bucket_sort: { + bucket_sort: { + sort: [{ activity_count: { order: 'desc' } }], + size: activityPageSize, + from: activityOffset, + }, + }, + }, + }, + }, + size: 0, + } as any + + if (filter.platforms) { + const subQueries = filter.platforms.map((p) => ({ match_phrase: { keyword_platform: p } })) + + activityQuery.query.bool.must.push({ + bool: { + should: subQueries, + }, + }) + } + + if (segmentsEnabled) { + const subQueries = segments.map((s) => ({ term: { uuid_segmentId: s } })) + + activityQuery.query.bool.must.push({ + bool: { + should: subQueries, + }, + }) + } + + const direction = orderBy.split('_')[1].toLowerCase() === 'desc' ? 'desc' : 'asc' + if (orderBy.startsWith('activityCount')) { + activityQuery.aggs.group_by_organization.aggs.active_organizations_bucket_sort.bucket_sort.sort = + [{ activity_count: { order: direction } }] + } else if (orderBy.startsWith('activeDaysCount')) { + activityQuery.aggs.group_by_organization.aggs.active_organizations_bucket_sort.bucket_sort.sort = + [{ active_days_count: { order: direction } }] + } else { + throw new Error(`Invalid order by: ${orderBy}`) + } + + const organizationIds = [] + let organizationMap = {} + let activities + + do { + activities = await options.opensearch.search({ + index: OpenSearchIndex.ACTIVITIES, + body: activityQuery, + }) + + organizationIds.push( + ...activities.body.aggregations.group_by_organization.buckets.map((b) => b.key), + ) + + organizationMap = { + ...organizationMap, + ...activities.body.aggregations.group_by_organization.buckets.reduce((acc, b) => { + acc[b.key] = { + activityCount: b.activity_count, + activeDaysCount: b.active_days_count, + } + + return acc + }, {}), + } + + activityOffset += activityPageSize + + // update page + activityQuery.aggs.group_by_organization.aggs.active_organizations_bucket_sort.bucket_sort.from = + activityOffset + } while (activities.body.aggregations.group_by_organization.buckets.length === activityPageSize) + + if (organizationIds.length === 0) { + return { + rows: [], + count: 0, + limit, + offset, + } + } + + const organizationQueryPayload = { + and: [ + { + id: { + in: organizationIds, + }, + }, + ], + } as any + + if (filter.isTeamOrganization === true) { + organizationQueryPayload.and.push({ + isTeamOrganization: { + eq: true, + }, + }) + } else if (filter.isTeamOrganization === false) { + organizationQueryPayload.and.push({ + isTeamOrganization: { + not: true, + }, + }) + } + + // to retain the sort came from activity query + const customSortFunction = { + _script: { + type: 'number', + script: { + lang: 'painless', + source: ` + def organizationId = doc['uuid_organizationId'].value; + return params.organizationIds.indexOf(organizationId); + `, + params: { + organizationIds: organizationIds.map((i) => `${i}`), + }, + }, + order: 'asc', + }, + } + + const organizations = await this.findAndCountAllOpensearch( + { + filter: organizationQueryPayload, + segments: [originalSegment], + countOnly: false, + limit, + offset, + customSortFunction, + }, + options, + ) + + return { + rows: organizations.rows.map((o) => { + o.activityCount = organizationMap[o.id].activityCount.value + o.activeDaysCount = organizationMap[o.id].activeDaysCount.value + return o + }), + count: organizations.count, + offset, + limit, + } + } + static async findAndCountAll( { filter = {} as any, diff --git a/backend/src/database/repositories/priorityLevelContextRepository.ts b/backend/src/database/repositories/priorityLevelContextRepository.ts new file mode 100644 index 0000000000..8466726600 --- /dev/null +++ b/backend/src/database/repositories/priorityLevelContextRepository.ts @@ -0,0 +1,30 @@ +import { IQueuePriorityCalculationContext } from '@crowd/types' +import { QueryTypes } from 'sequelize' +import { IRepositoryOptions } from './IRepositoryOptions' +import SequelizeRepository from './sequelizeRepository' + +export class PriorityLevelContextRepository { + public constructor(private readonly options: IRepositoryOptions) {} + + public async loadPriorityLevelContext( + tenantId: string, + ): Promise { + const seq = SequelizeRepository.getSequelize(this.options) + + const results = await seq.query( + `select plan, "priorityLevel" as "dbPriority" from tenants where id = :tenantId`, + { + replacements: { + tenantId, + }, + type: QueryTypes.SELECT, + }, + ) + + if (results.length === 1) { + return results[0] as IQueuePriorityCalculationContext + } + + throw new Error(`Tenant not found: ${tenantId}!`) + } +} diff --git a/backend/src/database/repositories/tenantRepository.ts b/backend/src/database/repositories/tenantRepository.ts index 547a9d729f..d3745bfd91 100644 --- a/backend/src/database/repositories/tenantRepository.ts +++ b/backend/src/database/repositories/tenantRepository.ts @@ -1,14 +1,13 @@ +import { Error400, Error404, getCleanString } from '@crowd/common' +import { Edition, TenantPlans } from '@crowd/types' import lodash from 'lodash' import Sequelize, { QueryTypes } from 'sequelize' -import { getCleanString, Error400, Error404 } from '@crowd/common' -import { Edition } from '@crowd/types' -import SequelizeRepository from './sequelizeRepository' -import AuditLogRepository from './auditLogRepository' +import { API_CONFIG } from '../../conf' import SequelizeFilterUtils from '../utils/sequelizeFilterUtils' import { isUserInTenant } from '../utils/userTenantUtils' import { IRepositoryOptions } from './IRepositoryOptions' -import Plans from '../../security/plans' -import { API_CONFIG } from '../../conf' +import AuditLogRepository from './auditLogRepository' +import SequelizeRepository from './sequelizeRepository' const { Op } = Sequelize @@ -17,7 +16,6 @@ const forbiddenTenantUrls = ['www'] class TenantRepository { static async getPayingTenantIds(options: IRepositoryOptions): Promise<({ id: string } & {})[]> { const database = SequelizeRepository.getSequelize(options) - const plans = Plans.values const transaction = SequelizeRepository.getTransaction(options) const query = ` @@ -31,7 +29,7 @@ class TenantRepository { type: QueryTypes.SELECT, transaction, replacements: { - growth: plans.growth, + growth: TenantPlans.Growth, }, }) } @@ -70,7 +68,7 @@ class TenantRepository { 'integrationsRequired', 'importHash', ]), - plan: API_CONFIG.edition === Edition.LFX ? Plans.values.enterprise : Plans.values.essential, + plan: API_CONFIG.edition === Edition.LFX ? TenantPlans.Enterprise : null, createdById: currentUser.id, updatedById: currentUser.id, }, @@ -119,7 +117,7 @@ class TenantRepository { ) if (checkTenantUrl.count > 0) { - cleanedTenantUrl += `-${checkTenantUrl.count}` + cleanedTenantUrl += `-${new Date().getTime()}` } return cleanedTenantUrl @@ -173,6 +171,8 @@ class TenantRepository { 'plan', 'isTrialPlan', 'trialEndsAt', + 'stripeSubscriptionId', + 'planSubscriptionEndsAt', ]), updatedById: currentUser.id, }, diff --git a/backend/src/database/repositories/types/memberTypes.ts b/backend/src/database/repositories/types/memberTypes.ts index 73c8efeca3..f957fd3e59 100644 --- a/backend/src/database/repositories/types/memberTypes.ts +++ b/backend/src/database/repositories/types/memberTypes.ts @@ -13,6 +13,7 @@ export interface IActiveMemberFilter { isBot?: boolean isTeamMember?: boolean isOrganization?: boolean + isDeleted?: boolean activityIsContribution?: boolean activityTimestampFrom: string activityTimestampTo: string diff --git a/backend/src/database/repositories/types/organizationTypes.ts b/backend/src/database/repositories/types/organizationTypes.ts new file mode 100644 index 0000000000..b3df938f36 --- /dev/null +++ b/backend/src/database/repositories/types/organizationTypes.ts @@ -0,0 +1,13 @@ +export interface IActiveOrganizationData { + id: string + displayName: string + activityCount: number + activeDaysCount: number +} + +export interface IActiveOrganizationFilter { + platforms?: string[] + isTeamOrganization?: boolean + activityTimestampFrom: string + activityTimestampTo: string +} diff --git a/backend/src/database/utils/sequelizeTestUtils.ts b/backend/src/database/utils/sequelizeTestUtils.ts index 949c0f2c5d..c08592c8d4 100644 --- a/backend/src/database/utils/sequelizeTestUtils.ts +++ b/backend/src/database/utils/sequelizeTestUtils.ts @@ -1,19 +1,18 @@ -import moment from 'moment' -import jwt from 'jsonwebtoken' -import bcrypt from 'bcrypt' import { getServiceLogger } from '@crowd/logging' import { getRedisClient } from '@crowd/redis' -import { SegmentStatus } from '@crowd/types' import { getTemporalClient } from '@crowd/temporal' +import { SegmentStatus, TenantPlans } from '@crowd/types' +import bcrypt from 'bcrypt' +import jwt from 'jsonwebtoken' +import moment from 'moment' +import { API_CONFIG, REDIS_CONFIG, TEMPORAL_CONFIG } from '../../conf' +import Roles from '../../security/roles' +import { IServiceOptions } from '../../services/IServiceOptions' import { databaseInit } from '../databaseConnection' import { IRepositoryOptions } from '../repositories/IRepositoryOptions' -import { IServiceOptions } from '../../services/IServiceOptions' -import Roles from '../../security/roles' -import UserRepository from '../repositories/userRepository' -import TenantRepository from '../repositories/tenantRepository' -import Plans from '../../security/plans' -import { API_CONFIG, REDIS_CONFIG, TEMPORAL_CONFIG } from '../../conf' import SettingsRepository from '../repositories/settingsRepository' +import TenantRepository from '../repositories/tenantRepository' +import UserRepository from '../repositories/userRepository' export default class SequelizeTestUtils { static async wipeDatabase(db) { @@ -59,7 +58,12 @@ export default class SequelizeTestUtils { return db } - static async getTestIServiceOptions(db, plan = Plans.values.essential, tenantName?, tenantUrl?) { + static async getTestIServiceOptions( + db, + plan: TenantPlans = TenantPlans.Essential, + tenantName?, + tenantUrl?, + ) { db = await this.getDatabase(db) const randomTenant = @@ -188,11 +192,11 @@ export default class SequelizeTestUtils { } as IRepositoryOptions } - static getRandomTestTenant(plan = Plans.values.essential) { + static getRandomTestTenant(plan = TenantPlans.Essential) { return this.getTenant(this.getRandomString('test-tenant'), this.getRandomString('url#'), plan) } - static getTenant(name, url, plan = Plans.values.essential) { + static getTenant(name, url, plan = TenantPlans.Essential) { return { name, url, diff --git a/backend/src/feature-flags/isFeatureEnabled.ts b/backend/src/feature-flags/isFeatureEnabled.ts index 05c89e5a93..6cd6c0ffe3 100644 --- a/backend/src/feature-flags/isFeatureEnabled.ts +++ b/backend/src/feature-flags/isFeatureEnabled.ts @@ -1,33 +1,7 @@ import { isFeatureEnabled } from '@crowd/feature-flags' import { FeatureFlag } from '@crowd/types' -import Plans from '../security/plans' import getFeatureFlagTenantContext from './getFeatureFlagTenantContext' -export const PLAN_LIMITS = { - [Plans.values.essential]: { - [FeatureFlag.AUTOMATIONS]: 2, - [FeatureFlag.CSV_EXPORT]: 2, - }, - [Plans.values.growth]: { - [FeatureFlag.AUTOMATIONS]: 10, - [FeatureFlag.CSV_EXPORT]: 10, - [FeatureFlag.MEMBER_ENRICHMENT]: 1000, - [FeatureFlag.ORGANIZATION_ENRICHMENT]: 200, - }, - [Plans.values.scale]: { - [FeatureFlag.AUTOMATIONS]: 20, - [FeatureFlag.CSV_EXPORT]: 20, - [FeatureFlag.MEMBER_ENRICHMENT]: Infinity, - [FeatureFlag.ORGANIZATION_ENRICHMENT]: Infinity, - }, - [Plans.values.enterprise]: { - [FeatureFlag.AUTOMATIONS]: Infinity, - [FeatureFlag.CSV_EXPORT]: Infinity, - [FeatureFlag.MEMBER_ENRICHMENT]: Infinity, - [FeatureFlag.ORGANIZATION_ENRICHMENT]: Infinity, - }, -} - export default async (featureFlag: FeatureFlag, req: any): Promise => isFeatureEnabled( featureFlag, diff --git a/backend/src/security/permissions.ts b/backend/src/security/permissions.ts index ed9f46cdb5..e108674ed1 100644 --- a/backend/src/security/permissions.ts +++ b/backend/src/security/permissions.ts @@ -1,10 +1,9 @@ +import { TenantPlans } from '@crowd/types' import Roles from './roles' -import Plans from './plans' import Storage from './storage' const storage = Storage.values const roles = Roles.values -const plans = Plans.values class Permissions { static get values() { @@ -13,132 +12,132 @@ class Permissions { id: 'tenantEdit', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, tenantDestroy: { id: 'tenantDestroy', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, planEdit: { id: 'planEdit', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, planRead: { id: 'planRead', allowedRoles: [roles.admin, roles.readonly], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, userEdit: { id: 'userEdit', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, userDestroy: { id: 'userDestroy', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, userCreate: { id: 'userCreate', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, userImport: { id: 'userImport', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, userRead: { id: 'userRead', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, userAutocomplete: { id: 'userAutocomplete', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, auditLogRead: { id: 'auditLogRead', allowedRoles: [roles.admin, roles.readonly], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, settingsRead: { id: 'settingsRead', allowedRoles: [roles.admin, roles.readonly], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], allowedStorage: [storage.settingsBackgroundImages, storage.settingsLogos], }, @@ -146,11 +145,11 @@ class Permissions { id: 'settingsEdit', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], allowedStorage: [storage.settingsBackgroundImages, storage.settingsLogos], }, @@ -158,11 +157,11 @@ class Permissions { id: 'memberAttributesRead', allowedRoles: [roles.admin, roles.readonly], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], allowedStorage: [], }, @@ -170,11 +169,11 @@ class Permissions { id: 'memberAttributesEdit', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], allowedStorage: [], }, @@ -182,11 +181,11 @@ class Permissions { id: 'memberAttributesDestroy', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], allowedStorage: [], }, @@ -194,11 +193,11 @@ class Permissions { id: 'memberAttributesCreate', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], allowedStorage: [], }, @@ -206,22 +205,22 @@ class Permissions { id: 'memberImport', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, memberCreate: { id: 'memberCreate', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], allowedStorage: [], }, @@ -229,11 +228,11 @@ class Permissions { id: 'memberEdit', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], allowedStorage: [], }, @@ -241,11 +240,11 @@ class Permissions { id: 'memberDestroy', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], allowedStorage: [], }, @@ -253,44 +252,44 @@ class Permissions { id: 'memberRead', allowedRoles: [roles.admin, roles.readonly], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, memberAutocomplete: { id: 'memberAutocomplete', allowedRoles: [roles.admin, roles.readonly], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, activityImport: { id: 'activityImport', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, activityCreate: { id: 'activityCreate', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], allowedStorage: [], }, @@ -298,11 +297,11 @@ class Permissions { id: 'activityEdit', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], allowedStorage: [], }, @@ -310,11 +309,11 @@ class Permissions { id: 'activityDestroy', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], allowedStorage: [], }, @@ -322,88 +321,88 @@ class Permissions { id: 'activityRead', allowedRoles: [roles.admin, roles.readonly], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, activityAutocomplete: { id: 'activityAutocomplete', allowedRoles: [roles.admin, roles.readonly], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, automationCreate: { id: 'automationCreate', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, automationUpdate: { id: 'automationUpdate', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, automationDestroy: { id: 'automationDestroy', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, automationRead: { id: 'automationRead', allowedRoles: [roles.admin, roles.readonly], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, tagImport: { id: 'tagImport', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, tagCreate: { id: 'tagCreate', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], allowedStorage: [], }, @@ -411,11 +410,11 @@ class Permissions { id: 'tagEdit', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], allowedStorage: [], }, @@ -423,11 +422,11 @@ class Permissions { id: 'tagDestroy', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], allowedStorage: [], }, @@ -435,44 +434,44 @@ class Permissions { id: 'tagRead', allowedRoles: [roles.admin, roles.readonly], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, tagAutocomplete: { id: 'tagAutocomplete', allowedRoles: [roles.admin, roles.readonly], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, organizationImport: { id: 'organizationImport', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, organizationCreate: { id: 'organizationCreate', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], allowedStorage: [], }, @@ -480,11 +479,11 @@ class Permissions { id: 'organizationEdit', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], allowedStorage: [], }, @@ -492,11 +491,11 @@ class Permissions { id: 'organizationDestroy', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], allowedStorage: [], }, @@ -504,44 +503,44 @@ class Permissions { id: 'organizationRead', allowedRoles: [roles.admin, roles.readonly], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, organizationAutocomplete: { id: 'organizationAutocomplete', allowedRoles: [roles.admin, roles.readonly], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, widgetImport: { id: 'widgetImport', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, widgetCreate: { id: 'widgetCreate', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], allowedStorage: [], }, @@ -549,11 +548,11 @@ class Permissions { id: 'widgetEdit', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], allowedStorage: [], }, @@ -561,11 +560,11 @@ class Permissions { id: 'widgetDestroy', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], allowedStorage: [], }, @@ -573,44 +572,44 @@ class Permissions { id: 'widgetRead', allowedRoles: [roles.admin, roles.readonly], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, widgetAutocomplete: { id: 'widgetAutocomplete', allowedRoles: [roles.admin, roles.readonly], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, reportImport: { id: 'reportImport', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, reportCreate: { id: 'reportCreate', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], allowedStorage: [], }, @@ -618,11 +617,11 @@ class Permissions { id: 'reportEdit', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], allowedStorage: [], }, @@ -630,11 +629,11 @@ class Permissions { id: 'reportDestroy', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], allowedStorage: [], }, @@ -642,33 +641,33 @@ class Permissions { id: 'reportRead', allowedRoles: [roles.admin, roles.readonly], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, reportAutocomplete: { id: 'reportAutocomplete', allowedRoles: [roles.admin, roles.readonly], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, integrationImport: { id: 'integrationImport', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, integrationControlLimit: { @@ -680,11 +679,11 @@ class Permissions { id: 'integrationCreate', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], allowedStorage: [], }, @@ -692,11 +691,11 @@ class Permissions { id: 'integrationEdit', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], allowedStorage: [], }, @@ -704,11 +703,11 @@ class Permissions { id: 'integrationDestroy', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], allowedStorage: [], }, @@ -716,44 +715,44 @@ class Permissions { id: 'integrationRead', allowedRoles: [roles.admin, roles.readonly], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, integrationAutocomplete: { id: 'integrationAutocomplete', allowedRoles: [roles.admin, roles.readonly], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, microserviceImport: { id: 'microserviceImport', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, microserviceCreate: { id: 'microserviceCreate', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], allowedStorage: [], }, @@ -761,11 +760,11 @@ class Permissions { id: 'microserviceEdit', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], allowedStorage: [], }, @@ -773,11 +772,11 @@ class Permissions { id: 'microserviceDestroy', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], allowedStorage: [], }, @@ -785,49 +784,54 @@ class Permissions { id: 'microserviceRead', allowedRoles: [roles.admin, roles.readonly], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, microserviceAutocomplete: { id: 'microserviceAutocomplete', allowedRoles: [roles.admin, roles.readonly], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, microserviceVariantFree: { id: 'microserviceVariantFree', allowedRoles: [roles.admin, roles.readonly], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, microserviceVariantPremium: { id: 'microserviceVariantPremium', allowedRoles: [roles.admin, roles.readonly], - allowedPlans: [plans.growth, plans.eagleEye, plans.enterprise, plans.scale], + allowedPlans: [ + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, + ], }, conversationCreate: { id: 'conversationCreate', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], allowedStorage: [], }, @@ -835,11 +839,11 @@ class Permissions { id: 'conversationEdit', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], allowedStorage: [], }, @@ -847,11 +851,11 @@ class Permissions { id: 'conversationDestroy', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], allowedStorage: [], }, @@ -859,99 +863,99 @@ class Permissions { id: 'conversationRead', allowedRoles: [roles.admin, roles.readonly], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, eagleEyeActionCreate: { id: 'eagleEyeActionCreate', allowedRoles: [roles.admin, roles.readonly], allowedPlans: [ - plans.growth, - plans.essential, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Growth, + TenantPlans.Essential, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, eagleEyeActionDestroy: { id: 'eagleEyeActionDestroy', allowedRoles: [roles.admin, roles.readonly], allowedPlans: [ - plans.growth, - plans.essential, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Growth, + TenantPlans.Essential, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, eagleEyeContentCreate: { id: 'eagleEyeContentCreate', allowedRoles: [roles.admin, roles.readonly], allowedPlans: [ - plans.growth, - plans.essential, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Growth, + TenantPlans.Essential, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, eagleEyeContentRead: { id: 'eagleEyeContentRead', allowedRoles: [roles.admin, roles.readonly], allowedPlans: [ - plans.growth, - plans.essential, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Growth, + TenantPlans.Essential, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, eagleEyeContentSearch: { id: 'eagleEyeContentSearch', allowedRoles: [roles.admin, roles.readonly], allowedPlans: [ - plans.growth, - plans.essential, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Growth, + TenantPlans.Essential, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, eagleEyeContentEdit: { id: 'eagleEyeContentEdit', allowedRoles: [roles.admin, roles.readonly], allowedPlans: [ - plans.growth, - plans.essential, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Growth, + TenantPlans.Essential, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, taskImport: { id: 'taskImport', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, taskCreate: { id: 'taskCreate', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], allowedStorage: [], }, @@ -959,11 +963,11 @@ class Permissions { id: 'taskEdit', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], allowedStorage: [], }, @@ -971,11 +975,11 @@ class Permissions { id: 'taskDestroy', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], allowedStorage: [], }, @@ -983,55 +987,55 @@ class Permissions { id: 'taskRead', allowedRoles: [roles.admin, roles.readonly], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, taskAutocomplete: { id: 'taskAutocomplete', allowedRoles: [roles.admin, roles.readonly], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, taskBatch: { id: 'taskBatch', allowedRoles: [roles.admin, roles.readonly], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, noteImport: { id: 'noteImport', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, noteCreate: { id: 'noteCreate', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], allowedStorage: [], }, @@ -1039,11 +1043,11 @@ class Permissions { id: 'noteEdit', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], allowedStorage: [], }, @@ -1051,11 +1055,11 @@ class Permissions { id: 'noteDestroy', allowedRoles: [roles.admin], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], allowedStorage: [], }, @@ -1063,121 +1067,121 @@ class Permissions { id: 'noteRead', allowedRoles: [roles.admin, roles.readonly], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, noteAutocomplete: { id: 'noteAutocomplete', allowedRoles: [roles.admin, roles.readonly], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, quickstartGuideRead: { id: 'quickstartGuideRead', allowedRoles: [roles.admin, roles.readonly], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, quickstartGuideSettingsUpdate: { id: 'quickstartGuideSettingsUpdate', allowedRoles: [roles.admin, roles.readonly], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, segmentRead: { id: 'segmentRead', allowedRoles: [roles.admin, roles.readonly], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, segmentCreate: { id: 'segmentCreate', allowedRoles: [roles.admin, roles.readonly], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, segmentEdit: { id: 'segmentEdit', allowedRoles: [roles.admin, roles.readonly], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, customViewCreate: { id: 'customViewCreate', allowedRoles: [roles.admin, roles.readonly], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, customViewEdit: { id: 'customViewEdit', allowedRoles: [roles.admin, roles.readonly], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, customViewDestroy: { id: 'customViewDestroy', allowedRoles: [roles.admin, roles.readonly], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, customViewRead: { id: 'customViewRead', allowedRoles: [roles.admin, roles.readonly], allowedPlans: [ - plans.essential, - plans.growth, - plans.eagleEye, - plans.enterprise, - plans.scale, + TenantPlans.Essential, + TenantPlans.Growth, + TenantPlans.EagleEye, + TenantPlans.Enterprise, + TenantPlans.Scale, ], }, } diff --git a/backend/src/security/plans.ts b/backend/src/security/plans.ts index 83f3bcf40b..aa1d4af20f 100644 --- a/backend/src/security/plans.ts +++ b/backend/src/security/plans.ts @@ -1,28 +1,19 @@ +import { TenantPlans } from '@crowd/types' import { PLANS_CONFIG } from '../conf' class Plans { - static get values() { - return { - essential: 'Essential', - growth: 'Growth', - eagleEye: 'Eagle Eye', - scale: 'Scale', - enterprise: 'Enterprise', - } - } - static selectPlanByStripePriceId(stripePriceId) { const premiumStripePriceId = PLANS_CONFIG.stripePricePremium if (premiumStripePriceId === stripePriceId) { - return Plans.values.growth + return TenantPlans.Growth } - return Plans.values.essential + return TenantPlans.Essential } static selectStripePriceIdByPlan(plan) { - if (plan === Plans.values.growth) { + if (plan === TenantPlans.Growth) { return PLANS_CONFIG.stripePricePremium } @@ -64,7 +55,7 @@ class Plans { * because future charges might occur */ static allowTenantDestroy(plan, planStatus) { - if (plan === Plans.values.essential || plan === Plans.values.growth) { + if (plan === TenantPlans.Essential || plan === TenantPlans.Growth) { return true } diff --git a/backend/src/segment/identifyTenant.ts b/backend/src/segment/identifyTenant.ts index 5456c8a20f..641d6461e9 100644 --- a/backend/src/segment/identifyTenant.ts +++ b/backend/src/segment/identifyTenant.ts @@ -11,9 +11,12 @@ export default async function identifyTenant(req) { analytics.group({ userId: req.currentUser.id, groupId: req.currentTenant.id, - traits: { - name: req.currentTenant.name, - }, + traits: + req.currentTenant.name !== 'temporaryName' + ? { + name: req.currentTenant.name, + } + : undefined, }) } } else if (API_CONFIG.edition === Edition.COMMUNITY) { diff --git a/backend/src/serverless/integrations/services/integrationProcessor.ts b/backend/src/serverless/integrations/services/integrationProcessor.ts index f74f190ab5..4fafe5b3c5 100644 --- a/backend/src/serverless/integrations/services/integrationProcessor.ts +++ b/backend/src/serverless/integrations/services/integrationProcessor.ts @@ -1,73 +1,20 @@ import { LoggerBase } from '@crowd/logging' -import { ApiPubSubEmitter, RedisClient } from '@crowd/redis' import IntegrationRunRepository from '../../../database/repositories/integrationRunRepository' -import IntegrationStreamRepository from '../../../database/repositories/integrationStreamRepository' import { IServiceOptions } from '../../../services/IServiceOptions' -import { NodeWorkerIntegrationProcessMessage } from '../../../types/mq/nodeWorkerIntegrationProcessMessage' -import { IntegrationRunProcessor } from './integrationRunProcessor' import { IntegrationTickProcessor } from './integrationTickProcessor' -import { WebhookProcessor } from './webhookProcessor' export class IntegrationProcessor extends LoggerBase { private readonly tickProcessor: IntegrationTickProcessor - private readonly webhookProcessor: WebhookProcessor - - private readonly runProcessor: IntegrationRunProcessor | undefined - - constructor(options: IServiceOptions, redisEmitterClient?: RedisClient) { + constructor(options: IServiceOptions) { super(options.log) - const integrationServices = [] - - this.log.debug( - { supportedIntegrations: integrationServices.map((i) => i.type) }, - 'Successfully detected supported integrations!', - ) - - let apiPubSubEmitter: ApiPubSubEmitter | undefined - - if (redisEmitterClient) { - apiPubSubEmitter = new ApiPubSubEmitter(redisEmitterClient, this.log) - } - const integrationRunRepository = new IntegrationRunRepository(options) - const integrationStreamRepository = new IntegrationStreamRepository(options) - this.tickProcessor = new IntegrationTickProcessor( - options, - integrationServices, - integrationRunRepository, - ) - - this.webhookProcessor = new WebhookProcessor(options, integrationServices) - - if (apiPubSubEmitter) { - this.runProcessor = new IntegrationRunProcessor( - options, - integrationServices, - integrationRunRepository, - integrationStreamRepository, - apiPubSubEmitter, - ) - } else { - this.log.warn('No apiPubSubEmitter provided, runProcessor will not be initialized!') - } + this.tickProcessor = new IntegrationTickProcessor(options, integrationRunRepository) } async processTick() { await this.tickProcessor.processTick() } - - async processWebhook(webhookId: string, force?: boolean, fireCrowdWebhooks?: boolean) { - await this.webhookProcessor.processWebhook(webhookId, force, fireCrowdWebhooks) - } - - async process(req: NodeWorkerIntegrationProcessMessage) { - if (this.runProcessor) { - await this.runProcessor.process(req) - } else { - throw new Error('runProcessor is not initialized!') - } - } } diff --git a/backend/src/serverless/integrations/services/integrationRunProcessor.ts b/backend/src/serverless/integrations/services/integrationRunProcessor.ts deleted file mode 100644 index 3575b726e4..0000000000 --- a/backend/src/serverless/integrations/services/integrationRunProcessor.ts +++ /dev/null @@ -1,573 +0,0 @@ -import moment from 'moment' -import { ApiPubSubEmitter } from '@crowd/redis' -import { Logger, getChildLogger, LoggerBase } from '@crowd/logging' -import { i18n, singleOrDefault } from '@crowd/common' -import { IntegrationRunState, PlatformType } from '@crowd/types' -import { sendSlackAlert, SlackAlertTypes } from '@crowd/alerting' -import IntegrationRepository from '../../../database/repositories/integrationRepository' -import IntegrationRunRepository from '../../../database/repositories/integrationRunRepository' -import IntegrationStreamRepository from '../../../database/repositories/integrationStreamRepository' -import MicroserviceRepository from '../../../database/repositories/microserviceRepository' -import getUserContext from '../../../database/utils/getUserContext' -import { twitterFollowers } from '../../../database/utils/keys/microserviceTypes' -import { IServiceOptions } from '../../../services/IServiceOptions' -import { - IIntegrationStream, - IProcessStreamResults, - IStepContext, -} from '../../../types/integration/stepResult' -import { IntegrationRun } from '../../../types/integrationRunTypes' -import { NodeWorkerIntegrationProcessMessage } from '../../../types/mq/nodeWorkerIntegrationProcessMessage' -import { IntegrationServiceBase } from './integrationServiceBase' -import SampleDataService from '../../../services/sampleDataService' -import { - DbIntegrationStreamCreateData, - IntegrationStream, - IntegrationStreamState, -} from '../../../types/integrationStreamTypes' -import bulkOperations from '../../dbOperations/operationsWorker' -import UserRepository from '../../../database/repositories/userRepository' -import EmailSender from '../../../services/emailSender' -import { API_CONFIG, SLACK_ALERTING_CONFIG } from '../../../conf' -import SegmentRepository from '../../../database/repositories/segmentRepository' - -export class IntegrationRunProcessor extends LoggerBase { - constructor( - options: IServiceOptions, - private readonly integrationServices: IntegrationServiceBase[], - private readonly integrationRunRepository: IntegrationRunRepository, - private readonly integrationStreamRepository: IntegrationStreamRepository, - private readonly apiPubSubEmitter?: ApiPubSubEmitter, - ) { - super(options.log) - } - - async process(req: NodeWorkerIntegrationProcessMessage) { - if (!req.runId) { - this.log.warn("No runId provided! Skipping because it's an old message.") - return - } - - this.log.info({ runId: req.runId }, 'Detected integration run!') - - const run = await this.integrationRunRepository.findById(req.runId) - - const userContext = await getUserContext(run.tenantId) - - let integration - - if (run.integrationId) { - integration = await IntegrationRepository.findById(run.integrationId, userContext) - } else if (run.microserviceId) { - const microservice = await MicroserviceRepository.findById(run.microserviceId, userContext) - - switch (microservice.type) { - case twitterFollowers: - integration = await IntegrationRepository.findByPlatform( - PlatformType.TWITTER, - userContext, - ) - break - default: - throw new Error(`Microservice type '${microservice.type}' is not supported!`) - } - } else { - this.log.error({ runId: req.runId }, 'Integration run has no integration or microservice!') - throw new Error(`Integration run '${req.runId}' has no integration or microservice!`) - } - - const segmentRepository = new SegmentRepository(userContext) - userContext.currentSegments = [await segmentRepository.findById(integration.segmentId)] - - const logger = getChildLogger('process', this.log, { - runId: req.runId, - type: integration.platform, - tenantId: integration.tenantId, - integrationId: run.integrationId, - onboarding: run.onboarding, - microserviceId: run.microserviceId, - }) - - logger.info('Processing integration!') - - userContext.log = logger - - // get the relevant integration service that is supposed to be configured already - const intService = singleOrDefault( - this.integrationServices, - (s) => s.type === integration.platform, - ) - if (intService === undefined) { - logger.error('No integration service configured!') - throw new Error(`No integration service configured for type '${integration.platform}'!`) - } - - const stepContext: IStepContext = { - startTimestamp: moment().utc().unix(), - limitCount: integration.limitCount || 0, - onboarding: run.onboarding, - pipelineData: {}, - runId: req.runId, - integration, - serviceContext: userContext, - repoContext: userContext, - logger, - } - - if (!req.streamId) { - const existingRun = await this.integrationRunRepository.findLastProcessingRun( - run.integrationId, - run.microserviceId, - req.runId, - ) - - if (existingRun) { - logger.info('Integration is already being processed!') - await this.integrationRunRepository.markError(req.runId, { - errorPoint: 'check_existing_run', - message: 'Integration is already being processed!', - existingRunId: existingRun.id, - }) - return - } - - if (run.state === IntegrationRunState.PROCESSED) { - logger.warn('Integration is already processed!') - return - } - - if (run.state === IntegrationRunState.PENDING) { - logger.info('Started processing integration!') - } else if (run.state === IntegrationRunState.DELAYED) { - logger.info('Continued processing delayed integration!') - } else if (run.state === IntegrationRunState.ERROR) { - logger.info('Restarted processing errored integration!') - } else if (run.state === IntegrationRunState.PROCESSING) { - throw new Error(`Invalid state '${run.state}' for integration run!`) - } - - await this.integrationRunRepository.markProcessing(req.runId) - run.state = IntegrationRunState.PROCESSING - - if (integration.settings.updateMemberAttributes) { - logger.trace('Updating member attributes!') - - await intService.createMemberAttributes(stepContext) - - integration.settings.updateMemberAttributes = false - await IntegrationRepository.update( - integration.id, - { settings: integration.settings }, - userContext, - ) - } - - // delete sample data on onboarding - if (run.onboarding) { - try { - await new SampleDataService(userContext).deleteSampleData() - } catch (err) { - logger.error(err, { tenantId: integration.tenantId }, 'Error deleting sample data!') - await this.integrationRunRepository.markError(req.runId, { - errorPoint: 'delete_sample_data', - message: err.message, - stack: err.stack, - errorString: JSON.stringify(err), - }) - return - } - } - } - - try { - // check global limit reset - if (intService.limitResetFrequencySeconds > 0 && integration.limitLastResetAt) { - const secondsSinceLastReset = moment() - .utc() - .diff(moment(integration.limitLastResetAt).utc(), 'seconds') - - if (secondsSinceLastReset >= intService.limitResetFrequencySeconds) { - integration.limitCount = 0 - integration.limitLastResetAt = moment().utc().toISOString() - - await IntegrationRepository.update( - integration.id, - { - limitCount: integration.limitCount, - limitLastResetAt: integration.limitLastResetAt, - }, - userContext, - ) - } - } - - // preprocess if needed - logger.trace('Preprocessing integration!') - try { - await intService.preprocess(stepContext) - } catch (err) { - if (err.rateLimitResetSeconds) { - // need to delay integration processing - logger.warn(err, 'Rate limit reached while preprocessing integration! Delaying...') - await this.handleRateLimitError(logger, run, err.rateLimitResetSeconds, stepContext) - return - } - - logger.error(err, 'Error preprocessing integration!') - await this.integrationRunRepository.markError(req.runId, { - errorPoint: 'preprocessing', - message: err.message, - stack: err.stack, - errorString: JSON.stringify(err), - }) - return - } - - // detect streams to process for this integration - - let forcedStream: IntegrationStream | undefined - if (req.streamId) { - forcedStream = await this.integrationStreamRepository.findById(req.streamId) - - if (!forcedStream) { - logger.error({ streamId: req.streamId }, 'Stream not found!') - throw new Error(`Stream '${req.streamId}' not found!`) - } - } else { - const dbStreams = await this.integrationStreamRepository.findByRunId(req.runId, 1, 1) - if (dbStreams.length > 0) { - logger.trace('Streams already detected and saved to the database!') - } else { - // need to optimize this as well since it may happen that we have a lot of streams - logger.trace('Detecting streams!') - try { - const pendingStreams = await intService.getStreams(stepContext) - const createStreams: DbIntegrationStreamCreateData[] = pendingStreams.map((s) => ({ - runId: req.runId, - tenantId: run.tenantId, - integrationId: run.integrationId, - microserviceId: run.microserviceId, - name: s.value, - metadata: s.metadata, - })) - await this.integrationStreamRepository.bulkCreate(createStreams) - await this.integrationRunRepository.touch(run.id) - } catch (err) { - if (err.rateLimitResetSeconds) { - // need to delay integration processing - logger.warn(err, 'Rate limit reached while getting integration streams! Delaying...') - await this.handleRateLimitError(logger, run, err.rateLimitResetSeconds, stepContext) - return - } - - throw err - } - } - } - - // process streams - let processedCount = 0 - let notifyCount = 0 - - let nextStream: IntegrationStream | undefined - if (forcedStream) { - nextStream = forcedStream - } else { - nextStream = await this.integrationStreamRepository.getNextStreamToProcess(req.runId) - } - - while (nextStream) { - if ((req as any).exiting) { - if (!run.onboarding) { - logger.warn('Stopped processing integration (not onboarding)!') - break - } else { - logger.warn('Stopped processing integration (onboarding)!') - const delayUntil = moment() - .add(3 * 60, 'seconds') - .toDate() - await this.integrationRunRepository.delay(req.runId, delayUntil) - break - } - } - - const stream: IIntegrationStream = { - id: nextStream.id, - value: nextStream.name, - metadata: nextStream.metadata, - } - - processedCount++ - notifyCount++ - - let processStreamResult: IProcessStreamResults - - logger.trace({ streamId: stream.id }, 'Processing stream!') - await this.integrationStreamRepository.markProcessing(stream.id) - await this.integrationRunRepository.touch(run.id) - try { - processStreamResult = await intService.processStream(stream, stepContext) - } catch (err) { - if (err.rateLimitResetSeconds) { - logger.warn( - { streamId: stream.id, message: err.message }, - 'Rate limit reached while processing stream! Delaying...', - ) - await this.handleRateLimitError( - logger, - run, - err.rateLimitResetSeconds, - stepContext, - stream, - ) - return - } - - const retries = await this.integrationStreamRepository.markError(stream.id, { - errorPoint: 'process_stream', - message: err.message, - stack: err.stack, - errorString: JSON.stringify(err), - }) - await this.integrationRunRepository.touch(run.id) - - logger.error(err, { retries, streamId: stream.id }, 'Error while processing stream!') - } - - if (processStreamResult) { - // surround with try catch so if one stream fails we try all of them as well just in case - try { - logger.trace({ stream: JSON.stringify(stream) }, `Processing stream results!`) - - if (processStreamResult.newStreams && processStreamResult.newStreams.length > 0) { - const dbCreateStreams: DbIntegrationStreamCreateData[] = - processStreamResult.newStreams.map((s) => ({ - runId: req.runId, - tenantId: run.tenantId, - integrationId: run.integrationId, - microserviceId: run.microserviceId, - name: s.value, - metadata: s.metadata, - })) - - await this.integrationStreamRepository.bulkCreate(dbCreateStreams) - await this.integrationRunRepository.touch(run.id) - - logger.info( - `Detected ${processStreamResult.newStreams.length} new streams to process!`, - ) - } - - for (const operation of processStreamResult.operations) { - if (operation.records.length > 0) { - logger.trace( - { operationType: operation.type }, - `Processing bulk operation with ${operation.records.length} records!`, - ) - stepContext.limitCount += operation.records.length - await bulkOperations( - operation.type, - operation.records, - userContext, - req.fireCrowdWebhooks ?? true, - ) - } - } - - if (processStreamResult.nextPageStream !== undefined) { - if ( - !run.onboarding && - (await intService.isProcessingFinished( - stepContext, - stream, - processStreamResult.operations, - processStreamResult.lastRecordTimestamp, - )) - ) { - logger.warn('Integration processing finished because of service implementation!') - } else { - logger.trace( - { currentStream: JSON.stringify(stream) }, - `Detected next page stream!`, - ) - await this.integrationStreamRepository.create({ - runId: req.runId, - tenantId: run.tenantId, - integrationId: run.integrationId, - microserviceId: run.microserviceId, - name: processStreamResult.nextPageStream.value, - metadata: processStreamResult.nextPageStream.metadata, - }) - await this.integrationRunRepository.touch(run.id) - } - } - - if (processStreamResult.sleep !== undefined && processStreamResult.sleep > 0) { - logger.warn( - `Stream processing resulted in a requested delay of ${processStreamResult.sleep}! Will delay remaining streams!`, - ) - - const delayUntil = moment().add(processStreamResult.sleep, 'seconds').toDate() - await this.integrationRunRepository.delay(req.runId, delayUntil) - break - } - - if (intService.globalLimit > 0 && stepContext.limitCount >= intService.globalLimit) { - // if limit reset frequency is 0 we don't need to care about limits - if (intService.limitResetFrequencySeconds > 0) { - logger.warn( - { - limitCount: stepContext.limitCount, - globalLimit: intService.globalLimit, - }, - 'We reached a global limit - stopping processing!', - ) - - integration.limitCount = stepContext.limitCount - - const secondsSinceLastReset = moment() - .utc() - .diff(moment(integration.limitLastResetAt).utc(), 'seconds') - - if (secondsSinceLastReset < intService.limitResetFrequencySeconds) { - const delayUntil = moment() - .add(intService.limitResetFrequencySeconds - secondsSinceLastReset, 'seconds') - .toDate() - await this.integrationRunRepository.delay(req.runId, delayUntil) - } - - break - } - } - - if (notifyCount === 50) { - logger.info(`Processed ${processedCount} streams!`) - notifyCount = 0 - } - - await this.integrationStreamRepository.markProcessed(stream.id) - await this.integrationRunRepository.touch(run.id) - } catch (err) { - logger.error( - err, - { stream: JSON.stringify(stream) }, - 'Error processing stream results!', - ) - await this.integrationStreamRepository.markError(stream.id, { - errorPoint: 'process_stream_results', - message: err.message, - stack: err.stack, - errorString: JSON.stringify(err), - }) - await this.integrationRunRepository.touch(run.id) - } - } - - if (forcedStream) { - break - } - - nextStream = await this.integrationStreamRepository.getNextStreamToProcess(req.runId) - } - - // postprocess integration settings - await intService.postprocess(stepContext) - - logger.info('Done processing integration!') - } catch (err) { - logger.error(err, 'Error while processing integration!') - } finally { - const newState = await this.integrationRunRepository.touchState(req.runId) - - let emailSentAt - if (newState === IntegrationRunState.PROCESSED) { - if (!integration.emailSentAt) { - const tenantUsers = await UserRepository.findAllUsersOfTenant(integration.tenantId) - emailSentAt = new Date() - for (const user of tenantUsers) { - await new EmailSender(EmailSender.TEMPLATES.INTEGRATION_DONE, { - integrationName: i18n('en', `entities.integration.name.${integration.platform}`), - link: API_CONFIG.frontendUrl, - }).sendTo(user.email) - } - } - } - - let status - switch (newState) { - case IntegrationRunState.PROCESSED: - status = 'done' - break - case IntegrationRunState.ERROR: - status = 'error' - break - default: - status = integration.status - } - - await IntegrationRepository.update( - integration.id, - { - status, - emailSentAt, - settings: stepContext.integration.settings, - refreshToken: stepContext.integration.refreshToken, - token: stepContext.integration.token, - }, - userContext, - ) - - if (newState === IntegrationRunState.PROCESSING && !req.streamId) { - const failedStreams = await this.integrationStreamRepository.findByRunId(req.runId, 1, 1, [ - IntegrationStreamState.ERROR, - ]) - if (failedStreams.length > 0) { - logger.warn('Integration ended but we are still processing - delaying for a minute!') - const delayUntil = moment().add(60, 'seconds') - await this.integrationRunRepository.delay(run.id, delayUntil.toDate()) - } else { - logger.error('Integration ended but we are still processing!') - } - } else if (newState === IntegrationRunState.ERROR) { - await sendSlackAlert({ - slackURL: SLACK_ALERTING_CONFIG.url, - alertType: SlackAlertTypes.INTEGRATION_ERROR, - integration, - userContext, - log: logger, - frameworkVersion: 'old', - }) - } - - if (run.onboarding && this.apiPubSubEmitter) { - this.apiPubSubEmitter.emitIntegrationCompleted(integration.tenantId, integration.id, status) - } - } - } - - private async handleRateLimitError( - logger: Logger, - run: IntegrationRun, - rateLimitResetSeconds: number, - context: IStepContext, - stream?: IIntegrationStream, - ): Promise { - await IntegrationRepository.update( - context.integration.id, - { - settings: context.integration.settings, - refreshToken: context.integration.refreshToken, - token: context.integration.token, - }, - context.repoContext, - ) - - logger.warn('Rate limit reached, delaying integration processing!') - const delayUntil = moment().add(rateLimitResetSeconds + 30, 'seconds') - await this.integrationRunRepository.delay(run.id, delayUntil.toDate()) - - if (stream) { - await this.integrationStreamRepository.reset(stream.id) - } - } -} diff --git a/backend/src/serverless/integrations/services/integrationServiceBase.ts b/backend/src/serverless/integrations/services/integrationServiceBase.ts deleted file mode 100644 index 6e459dbe0a..0000000000 --- a/backend/src/serverless/integrations/services/integrationServiceBase.ts +++ /dev/null @@ -1,181 +0,0 @@ -import { SuperfaceClient } from '@superfaceai/one-sdk' -import moment from 'moment' -import crypto from 'crypto' -import { getServiceChildLogger } from '@crowd/logging' -import { IntegrationRunState, IntegrationType } from '@crowd/types' -import { IRepositoryOptions } from '../../../database/repositories/IRepositoryOptions' -import { - IIntegrationStream, - IPendingStream, - IProcessStreamResults, - IProcessWebhookResults, - IStepContext, - IStreamResultOperation, -} from '../../../types/integration/stepResult' -import { IS_TEST_ENV } from '../../../conf' -import { sendNodeWorkerMessage } from '../../utils/nodeWorkerSQS' -import { NodeWorkerIntegrationProcessMessage } from '../../../types/mq/nodeWorkerIntegrationProcessMessage' -import IntegrationRunRepository from '../../../database/repositories/integrationRunRepository' - -const logger = getServiceChildLogger('integrationService') - -/* eslint class-methods-use-this: 0 */ - -/* eslint-disable @typescript-eslint/no-unused-vars */ - -export abstract class IntegrationServiceBase { - /** - * How many records to process before we stop - */ - public globalLimit: number - - /** - * If onboarding globalLimit will be multiplied by this factor for that run - */ - public onboardingLimitModifierFactor: number - - /** - * How many seconds between global limit reset (0 for auto reset) - */ - public limitResetFrequencySeconds: number - - /** - * Every new integration should extend this class and implement its methods. - * - * @param type What integration is this? - * @param ticksBetweenChecks How many ticks to skip between each integration checks (each tick is 1 minute). If 0 it will be triggered every tick same as if it was 1. If negative it will never be triggered. - */ - protected constructor( - public readonly type: IntegrationType, - public readonly ticksBetweenChecks: number, - ) { - this.globalLimit = 0 - this.onboardingLimitModifierFactor = 1.0 - this.limitResetFrequencySeconds = 0 - } - - async triggerIntegrationCheck(integrations: any[], options: IRepositoryOptions): Promise { - const repository = new IntegrationRunRepository(options) - - for (const integration of integrations) { - const run = await repository.create({ - integrationId: integration.id, - tenantId: integration.tenantId, - onboarding: false, - state: IntegrationRunState.PENDING, - }) - - logger.info( - { integrationId: integration.id, runId: run.id }, - 'Triggering integration processing!', - ) - await sendNodeWorkerMessage( - integration.tenantId, - new NodeWorkerIntegrationProcessMessage(run.id), - ) - } - } - - async preprocess(context: IStepContext): Promise { - // do nothing - override if something is needed - } - - async createMemberAttributes(context: IStepContext): Promise { - // do nothing - override if something is needed - } - - abstract getStreams(context: IStepContext): Promise - - abstract processStream( - stream: IIntegrationStream, - context: IStepContext, - ): Promise - - async isProcessingFinished( - context: IStepContext, - currentStream: IIntegrationStream, - lastOperations: IStreamResultOperation[], - lastRecord?: any, - lastRecordTimestamp?: number, - ): Promise { - return false - } - - async postprocess(context: IStepContext): Promise { - // do nothing - override if something is needed - } - - async processWebhook(webhook: any, context: IStepContext): Promise { - throw new Error('Not implemented') - } - - static superfaceClient(): SuperfaceClient { - if (IS_TEST_ENV) { - return undefined - } - - return new SuperfaceClient() - } - - /** - * Check whether the last record is over the retrospect that we are interested in - * @param lastRecordTimestamp The last activity timestamp we got - * @param startTimestamp The timestamp when we started - * @param maxRetrospect The maximum time we want to crawl - * @returns Whether we are over the retrospect already - */ - static isRetrospectOver( - lastRecordTimestamp: number, - startTimestamp: number, - maxRetrospect: number, - ): boolean { - return startTimestamp - moment(lastRecordTimestamp).unix() > maxRetrospect - } - - /** - * Some activities will not have a remote(API) counterparts so they will miss sourceIds. - * Since we're using sourceIds to find out if an activity already exists in our DB, - * sourceIds are required when creating an activity. - * This function generates an md5 hash that can be used as a sourceId of an activity. - * Prepends string `gen-` to the beginning so generated and remote sourceIds - * can be distinguished. - * - * @param {string} uniqueRemoteId remote member id from an integration. This id needs to be unique in a platform - * @param {string} type type of the activity - * @param {string} timestamp unix timestamp of the activity - * @param {string} platform platform of the activity - * @returns 32 bit md5 hash generated from the given data, prepended with string `gen-` - */ - static generateSourceIdHash( - uniqueRemoteId: string, - type: string, - timestamp: string, - platform: string, - ) { - if (!uniqueRemoteId || !type || !timestamp || !platform) { - throw new Error('Bad hash input') - } - - const data = `${uniqueRemoteId}-${type}-${timestamp}-${platform}` - return `gen-${crypto.createHash('md5').update(data).digest('hex')}` - } - - /** - * Get the number of seconds from a date to a unix timestamp. - * Adding a 25% padding for security. - * If the unix timestamp is before the date, return 3 minutes for security - * @param date The date to get the seconds from - * @param unixTimestamp The unix timestamp to get the seconds from - * @returns The number of seconds from the date to the unix timestamp - */ - static secondsUntilTimestamp( - unixTimestamp: number, - date: Date = moment().utc().toDate(), - ): number { - const timestampedDate: number = moment.utc(date).unix() - if (timestampedDate > unixTimestamp) { - return 60 * 3 - } - return Math.floor(unixTimestamp - timestampedDate) - } -} diff --git a/backend/src/serverless/integrations/services/integrationTickProcessor.ts b/backend/src/serverless/integrations/services/integrationTickProcessor.ts index 183e59d508..4e5ea98e60 100644 --- a/backend/src/serverless/integrations/services/integrationTickProcessor.ts +++ b/backend/src/serverless/integrations/services/integrationTickProcessor.ts @@ -1,26 +1,20 @@ import { processPaginated, singleOrDefault } from '@crowd/common' -import { INTEGRATION_SERVICES } from '@crowd/integrations' -import { LoggerBase, getChildLogger } from '@crowd/logging' import { + DataSinkWorkerEmitter, IntegrationRunWorkerEmitter, IntegrationStreamWorkerEmitter, - DataSinkWorkerEmitter, -} from '@crowd/sqs' -import { IntegrationRunState, IntegrationType } from '@crowd/types' -import SequelizeRepository from '@/database/repositories/sequelizeRepository' -import MicroserviceRepository from '@/database/repositories/microserviceRepository' +} from '@crowd/common_services' +import { INTEGRATION_SERVICES } from '@crowd/integrations' +import { LoggerBase, getChildLogger } from '@crowd/logging' +import { IntegrationType, TenantPlans } from '@crowd/types' import IntegrationRepository from '@/database/repositories/integrationRepository' -import { IRepositoryOptions } from '@/database/repositories/IRepositoryOptions' import IntegrationRunRepository from '../../../database/repositories/integrationRunRepository' import { IServiceOptions } from '../../../services/IServiceOptions' -import { NodeWorkerIntegrationProcessMessage } from '../../../types/mq/nodeWorkerIntegrationProcessMessage' -import { sendNodeWorkerMessage } from '../../utils/nodeWorkerSQS' import { + getDataSinkWorkerEmitter, getIntegrationRunWorkerEmitter, getIntegrationStreamWorkerEmitter, - getDataSinkWorkerEmitter, } from '../../utils/serviceSQS' -import { IntegrationServiceBase } from './integrationServiceBase' export class IntegrationTickProcessor extends LoggerBase { private tickTrackingMap: Map = new Map() @@ -35,15 +29,10 @@ export class IntegrationTickProcessor extends LoggerBase { constructor( options: IServiceOptions, - private readonly integrationServices: IntegrationServiceBase[], private readonly integrationRunRepository: IntegrationRunRepository, ) { super(options.log) - for (const intService of this.integrationServices) { - this.tickTrackingMap[intService.type] = 0 - } - for (const intService of INTEGRATION_SERVICES) { this.tickTrackingMap[intService.type] = 0 } @@ -67,18 +56,11 @@ export class IntegrationTickProcessor extends LoggerBase { private async processCheckTick() { this.log.trace('Processing integration processor tick!') - const tickers: IIntTicker[] = this.integrationServices.map((i) => ({ + const tickers: IIntTicker[] = INTEGRATION_SERVICES.map((i) => ({ type: i.type, - ticksBetweenChecks: i.ticksBetweenChecks, + ticksBetweenChecks: i.checkEvery || -1, })) - for (const service of INTEGRATION_SERVICES) { - tickers.push({ - type: service.type, - ticksBetweenChecks: service.checkEvery || -1, - }) - } - const promises: Promise[] = [] for (const intService of tickers) { @@ -121,134 +103,75 @@ export class IntegrationTickProcessor extends LoggerBase { const logger = getChildLogger('processCheck', this.log, { IntegrationType: type }) logger.trace('Processing integration check!') - if (type === IntegrationType.TWITTER_REACH) { - await processPaginated( - async (page) => MicroserviceRepository.findAllByType('twitter_followers', page, 10), - async (microservices) => { - this.log.debug({ type, count: microservices.length }, 'Found microservices to check!') - for (const micro of microservices) { - const existingRun = await this.integrationRunRepository.findLastProcessingRun( - undefined, - micro.id, - ) - if (!existingRun) { - const microservice = micro as any + const newIntService = singleOrDefault(INTEGRATION_SERVICES, (i) => i.type === type) - const run = await this.integrationRunRepository.create({ - microserviceId: microservice.id, - tenantId: microservice.tenantId, - onboarding: false, - state: IntegrationRunState.PENDING, - }) - - this.log.debug({ type, runId: run.id }, 'Triggering microservice processing!') - - await sendNodeWorkerMessage( - microservice.tenantId, - new NodeWorkerIntegrationProcessMessage(run.id), - ) - } - } - }, - ) - } else { - const options = - (await SequelizeRepository.getDefaultIRepositoryOptions()) as IRepositoryOptions - - // get the relevant integration service that is supposed to be configured already - const intService = singleOrDefault(this.integrationServices, (s) => s.type === type) + if (!newIntService) { + throw new Error(`No integration service found for type ${type}!`) + } - if (intService) { - await processPaginated( - async (page) => IntegrationRepository.findAllActive(type, page, 10), - async (integrations) => { - logger.debug( - { integrationIds: integrations.map((i) => i.id) }, - 'Found old integrations to check!', - ) - const inactiveIntegrations: any[] = [] - for (const integration of integrations as any[]) { - const existingRun = await this.integrationRunRepository.findLastProcessingRun( - integration.id, - ) - if (!existingRun) { - inactiveIntegrations.push(integration) - } - } + const emitter = await getIntegrationRunWorkerEmitter() - if (inactiveIntegrations.length > 0) { + await processPaginated( + async (page) => IntegrationRepository.findAllActive(type, page, 10), + async (integrations) => { + logger.debug( + { integrationIds: integrations.map((i) => i.id) }, + 'Found new integrations to check!', + ) + for (const integration of integrations as any[]) { + const existingRun = + await this.integrationRunRepository.findLastProcessingRunInNewFramework(integration.id) + if (!existingRun) { + const CHUNKS = 3 // Define the number of chunks + const DELAY_BETWEEN_CHUNKS = 30 * 60 * 1000 // Define the delay between chunks in milliseconds + const rand = Math.random() * CHUNKS + const chunkIndex = Math.min(Math.floor(rand), CHUNKS - 1) + const delay = chunkIndex * DELAY_BETWEEN_CHUNKS + + if ( + newIntService.type === IntegrationType.DISCORD && + integration.tenant.plan === TenantPlans.Essential + ) { + // not triggering discord integrations for essential plan, only paid plans logger.info( - { integrationIds: inactiveIntegrations.map((i) => i.id) }, - 'Triggering old integration checks!', + { integrationId: integration.id }, + 'Not triggering new integration check for Discord for essential plan!', ) - await intService.triggerIntegrationCheck(inactiveIntegrations, options) + // eslint-disable-next-line no-continue + continue } - }, - ) - } else { - const newIntService = singleOrDefault(INTEGRATION_SERVICES, (i) => i.type === type) - - if (!newIntService) { - throw new Error(`No integration service found for type ${type}!`) - } - - const emitter = await getIntegrationRunWorkerEmitter() - await processPaginated( - async (page) => IntegrationRepository.findAllActive(type, page, 10), - async (integrations) => { - logger.debug( - { integrationIds: integrations.map((i) => i.id) }, - 'Found new integrations to check!', - ) - for (const integration of integrations as any[]) { - const existingRun = - await this.integrationRunRepository.findLastProcessingRunInNewFramework( + // Divide integrations into chunks for Discord + if (newIntService.type === IntegrationType.DISCORD) { + setTimeout(async () => { + logger.info( + { integrationId: integration.id }, + `Triggering new delayed integration check for Discord in ${ + delay / 60 / 1000 + } minutes!`, + ) + await emitter.triggerIntegrationRun( + integration.tenantId, + integration.platform, integration.id, + false, ) - if (!existingRun) { - const CHUNKS = 3 // Define the number of chunks - const DELAY_BETWEEN_CHUNKS = 30 * 60 * 1000 // Define the delay between chunks in milliseconds - const rand = Math.random() * CHUNKS - const chunkIndex = Math.min(Math.floor(rand), CHUNKS - 1) - const delay = chunkIndex * DELAY_BETWEEN_CHUNKS - - // Divide integrations into chunks for Discord - if (newIntService.type === IntegrationType.DISCORD) { - setTimeout(async () => { - logger.info( - { integrationId: integration.id }, - `Triggering new delayed integration check for Discord in ${ - delay / 60 / 1000 - } minutes!`, - ) - await emitter.triggerIntegrationRun( - integration.tenantId, - integration.platform, - integration.id, - false, - ) - }, delay) - } else { - logger.info( - { integrationId: integration.id }, - 'Triggering new integration check!', - ) - await emitter.triggerIntegrationRun( - integration.tenantId, - integration.platform, - integration.id, - false, - ) - } - } else { - logger.info({ integrationId: integration.id }, 'Existing run found, skipping!') - } + }, delay) + } else { + logger.info({ integrationId: integration.id }, 'Triggering new integration check!') + await emitter.triggerIntegrationRun( + integration.tenantId, + integration.platform, + integration.id, + false, + ) } - }, - ) - } - } + } else { + logger.info({ integrationId: integration.id }, 'Existing run found, skipping!') + } + } + }, + ) } private async processDelayedTick() { @@ -256,23 +179,6 @@ export class IntegrationTickProcessor extends LoggerBase { await this.intRunWorkerEmitter.checkRuns() await this.intStreamWorkerEmitter.checkStreams() await this.dataSinkWorkerEmitter.checkResults() - - // TODO check streams as well - this.log.trace('Checking for delayed integration runs!') - - await processPaginated( - async (page) => this.integrationRunRepository.findDelayedRuns(page, 10), - async (delayedRuns) => { - for (const run of delayedRuns) { - this.log.info({ runId: run.id }, 'Triggering delayed integration run processing!') - - await sendNodeWorkerMessage( - new Date().toISOString(), - new NodeWorkerIntegrationProcessMessage(run.id), - ) - } - }, - ) } } diff --git a/backend/src/serverless/integrations/services/webhookProcessor.ts b/backend/src/serverless/integrations/services/webhookProcessor.ts deleted file mode 100644 index af4ad4d1d1..0000000000 --- a/backend/src/serverless/integrations/services/webhookProcessor.ts +++ /dev/null @@ -1,130 +0,0 @@ -import { LoggerBase, getChildLogger } from '@crowd/logging' -import moment from 'moment' -import { singleOrDefault } from '@crowd/common' -import { IRepositoryOptions } from '../../../database/repositories/IRepositoryOptions' -import IncomingWebhookRepository from '../../../database/repositories/incomingWebhookRepository' -import IntegrationRepository from '../../../database/repositories/integrationRepository' -import SequelizeRepository from '../../../database/repositories/sequelizeRepository' -import getUserContext from '../../../database/utils/getUserContext' -import { IServiceOptions } from '../../../services/IServiceOptions' -import { IStepContext } from '../../../types/integration/stepResult' -import { NodeWorkerProcessWebhookMessage } from '../../../types/mq/nodeWorkerProcessWebhookMessage' -import { WebhookState } from '../../../types/webhooks' -import bulkOperations from '../../dbOperations/operationsWorker' -import { sendNodeWorkerMessage } from '../../utils/nodeWorkerSQS' -import { IntegrationServiceBase } from './integrationServiceBase' -import SegmentRepository from '../../../database/repositories/segmentRepository' - -export class WebhookProcessor extends LoggerBase { - constructor( - options: IServiceOptions, - private readonly integrationServices: IntegrationServiceBase[], - ) { - super(options.log) - } - - static readonly MAX_RETRY_LIMIT = 5 - - async processWebhook(webhookId: string, force?: boolean, fireCrowdWebhooks?: boolean) { - const options = (await SequelizeRepository.getDefaultIRepositoryOptions()) as IRepositoryOptions - const repo = new IncomingWebhookRepository(options) - const webhook = await repo.findById(webhookId) - let logger = getChildLogger('processWebhook', this.log, { webhookId }) - - if (webhook === null || webhook === undefined) { - logger.error('Webhook not found!') - return - } - - logger.debug('Processing webhook!') - - logger = getChildLogger('processWebhook', this.log, { - type: webhook.type, - tenantId: webhook.tenantId, - integrationId: webhook.integrationId, - }) - - logger.debug('Webhook found!') - - if (!(force === true) && webhook.state !== WebhookState.PENDING) { - logger.error({ state: webhook.state }, 'Webhook is not in pending state!') - return - } - - const userContext = await getUserContext(webhook.tenantId) - userContext.log = logger - - const integration = await IntegrationRepository.findById(webhook.integrationId, userContext) - if (integration.platform === 'github' || integration.platform === 'discord') { - return - } - const segment = await new SegmentRepository(userContext).findById(integration.segmentId) - userContext.currentSegments = [segment] - - const intService = singleOrDefault( - this.integrationServices, - (s) => s.type === integration.platform, - ) - if (intService === undefined) { - logger.error('No integration service configured!') - throw new Error(`No integration service configured for type '${integration.platform}'!`) - } - - const stepContext: IStepContext = { - startTimestamp: moment().utc().unix(), - limitCount: integration.limitCount || 0, - onboarding: false, - pipelineData: {}, - webhook, - integration, - serviceContext: userContext, - repoContext: userContext, - logger, - } - - if (integration.settings.updateMemberAttributes) { - logger.trace('Updating member attributes!') - - await intService.createMemberAttributes(stepContext) - - integration.settings.updateMemberAttributes = false - await IntegrationRepository.update( - integration.id, - { settings: integration.settings }, - userContext, - ) - } - - const whContext = { ...userContext } - whContext.transaction = await SequelizeRepository.createTransaction(whContext) - - try { - const result = await intService.processWebhook(webhook, stepContext) - for (const operation of result.operations) { - if (operation.records.length > 0) { - logger.trace( - { operationType: operation.type }, - `Processing bulk operation with ${operation.records.length} records!`, - ) - await bulkOperations(operation.type, operation.records, userContext, fireCrowdWebhooks) - } - } - await repo.markCompleted(webhook.id) - logger.debug('Webhook processed!') - } catch (err) { - if (err.rateLimitResetSeconds) { - logger.warn(err, 'Rate limit reached while processing webhook! Delaying...') - await sendNodeWorkerMessage( - integration.tenantId, - new NodeWorkerProcessWebhookMessage(integration.tenantId, webhookId), - err.rateLimitResetSeconds + 5, - ) - } else { - logger.error(err, 'Error processing webhook!') - await repo.markError(webhook.id, err) - } - } finally { - await SequelizeRepository.commitTransaction(whContext.transaction) - } - } -} diff --git a/backend/src/serverless/integrations/workers/sendgridWebhookWorker.ts b/backend/src/serverless/integrations/workers/sendgridWebhookWorker.ts index f66833339c..645407dd04 100644 --- a/backend/src/serverless/integrations/workers/sendgridWebhookWorker.ts +++ b/backend/src/serverless/integrations/workers/sendgridWebhookWorker.ts @@ -1,15 +1,13 @@ import { getServiceChildLogger } from '@crowd/logging' -import { EventWebhook, EventWebhookHeader } from '@sendgrid/eventwebhook' import { PlatformType } from '@crowd/types' +import { EventWebhook, EventWebhookHeader } from '@sendgrid/eventwebhook' +import { getNodejsWorkerEmitter } from '@/serverless/utils/serviceSQS' import { IS_PROD_ENV, SENDGRID_CONFIG } from '../../../conf' import SequelizeRepository from '../../../database/repositories/sequelizeRepository' import UserRepository from '../../../database/repositories/userRepository' import getUserContext from '../../../database/utils/getUserContext' import EagleEyeContentService from '../../../services/eagleEyeContentService' -import { NodeWorkerMessageBase } from '../../../types/mq/nodeWorkerMessageBase' import { SendgridWebhookEvent, SendgridWebhookEventType } from '../../../types/webhooks' -import { NodeWorkerMessageType } from '../../types/workerTypes' -import { sendNodeWorkerMessage } from '../../utils/nodeWorkerSQS' const log = getServiceChildLogger('sendgridWebhookWorker') @@ -46,13 +44,10 @@ export default async function sendgridWebhookWorker(req) { } } + const emitter = await getNodejsWorkerEmitter() for (const event of events) { if (event.sg_template_id === SENDGRID_CONFIG.templateEagleEyeDigest) { - await sendNodeWorkerMessage(event.sg_event_id, { - type: NodeWorkerMessageType.NODE_MICROSERVICE, - event, - service: 'sendgrid-webhooks', - } as NodeWorkerMessageBase) + await emitter.sendgridWebhook(event) } } diff --git a/backend/src/serverless/integrations/workers/stripeWebhookWorker.ts b/backend/src/serverless/integrations/workers/stripeWebhookWorker.ts index 813d1c2f3a..be48955cf5 100644 --- a/backend/src/serverless/integrations/workers/stripeWebhookWorker.ts +++ b/backend/src/serverless/integrations/workers/stripeWebhookWorker.ts @@ -1,15 +1,13 @@ +import { Error404, timeout } from '@crowd/common' import { getServiceChildLogger } from '@crowd/logging' -import { getRedisClient, RedisPubSubEmitter } from '@crowd/redis' +import { RedisPubSubEmitter, getRedisClient } from '@crowd/redis' +import { ApiWebsocketMessage } from '@crowd/types' import moment from 'moment' import { Stripe } from 'stripe' -import { timeout } from '@crowd/common' -import { ApiWebsocketMessage } from '@crowd/types' +import StripeService from '@/services/stripeService' +import { getNodejsWorkerEmitter } from '@/serverless/utils/serviceSQS' import { PLANS_CONFIG, REDIS_CONFIG } from '../../../conf' import SequelizeRepository from '../../../database/repositories/sequelizeRepository' -import Plans from '../../../security/plans' -import { NodeWorkerMessageBase } from '../../../types/mq/nodeWorkerMessageBase' -import { NodeWorkerMessageType } from '../../types/workerTypes' -import { sendNodeWorkerMessage } from '../../utils/nodeWorkerSQS' const log = getServiceChildLogger('stripeWebhookWorker') @@ -24,11 +22,8 @@ export default async function stripeWebhookWorker(req) { try { event = stripe.webhooks.constructEvent(req.rawBody, sig, PLANS_CONFIG.stripWebhookSigningSecret) - await sendNodeWorkerMessage(event.id, { - type: NodeWorkerMessageType.NODE_MICROSERVICE, - event, - service: 'stripe-webhooks', - } as NodeWorkerMessageBase) + const emitter = await getNodejsWorkerEmitter() + await emitter.stripeWebhook(event) } catch (err) { log.error(`Webhook Error: ${err.message}`) return { @@ -59,6 +54,62 @@ export const processStripeWebhook = async (message: any) => { const stripeWebhookMessage = message.event switch (stripeWebhookMessage.type) { + case 'customer.subscription.updated': { + const tenant = await options.database.tenant.findOne({ + where: { stripeSubscriptionId: stripeWebhookMessage.data.object.id }, + }) + + if (!tenant) { + throw new Error404() + } + + const subscription = await StripeService.retreiveSubscription( + stripeWebhookMessage.data.object.id, + ) + + const productId = (subscription as any).plan.product + + const trialEnd = subscription.trial_end + + const subscriptionEndsAt = subscription.current_period_end + + const productPlan = StripeService.getPlanFromProductId(productId) + + if (!productPlan) { + throw new Error404() + } + + const trialPeriod = moment(trialEnd, 'X').isAfter(moment()) + + await tenant.update({ + plan: ['active', 'trialing'].includes(subscription.status) ? productPlan : null, + isTrialPlan: !!trialEnd && trialPeriod, + trialEndsAt: trialEnd && trialPeriod ? moment(trialEnd, 'X').toISOString() : null, + stripeSubscriptionId: subscription.id, + planSubscriptionEndsAt: moment(subscriptionEndsAt, 'X').toISOString(), + }) + + break + } + case 'customer.subscription.deleted': { + const tenant = await options.database.tenant.findOne({ + where: { stripeSubscriptionId: stripeWebhookMessage.data.object.id }, + }) + + if (!tenant) { + throw new Error404() + } + + await tenant.update({ + plan: null, + isTrialPlan: false, + trialEndsAt: null, + stripeSubscriptionId: stripeWebhookMessage.data.object.id, + planSubscriptionEndsAt: moment().toISOString(), + }) + + break + } case 'checkout.session.completed': { log.info( { tenant: stripeWebhookMessage.data.object.client_reference_id }, @@ -66,7 +117,7 @@ export const processStripeWebhook = async (message: any) => { ) // get subscription information from checkout event - const subscription = await stripe.subscriptions.retrieve( + const subscription = await StripeService.retreiveSubscription( stripeWebhookMessage.data.object.subscription, ) @@ -74,14 +125,10 @@ export const processStripeWebhook = async (message: any) => { const tenantId = stripeWebhookMessage.data.object.client_reference_id const tenant = await options.database.tenant.findByPk(tenantId) + const productId = (subscription as any).plan.product + const productPlan = StripeService.getPlanFromProductId(productId) - let productPlan - - if ((subscription as any).plan.product === PLANS_CONFIG.stripeEagleEyePlanProductId) { - productPlan = Plans.values.eagleEye - } else if ((subscription as any).plan.product === PLANS_CONFIG.stripeGrowthPlanProductId) { - productPlan = Plans.values.growth - } else { + if (!productPlan) { log.error({ subscription }, `Unknown product in subscription`) process.exit(1) } diff --git a/backend/src/serverless/microservices/nodejs/bulk-enrichment/bulkOrganizationEnrichmentWorker.ts b/backend/src/serverless/microservices/nodejs/bulk-enrichment/bulkOrganizationEnrichmentWorker.ts index b94929e763..85c67e6f10 100644 --- a/backend/src/serverless/microservices/nodejs/bulk-enrichment/bulkOrganizationEnrichmentWorker.ts +++ b/backend/src/serverless/microservices/nodejs/bulk-enrichment/bulkOrganizationEnrichmentWorker.ts @@ -1,9 +1,8 @@ import { getRedisClient, RedisCache } from '@crowd/redis' -import { FeatureFlag, FeatureFlagRedisKey } from '@crowd/types' +import { FeatureFlag, FeatureFlagRedisKey, PLAN_LIMITS } from '@crowd/types' import { getSecondsTillEndOfMonth } from '../../../../utils/timing' import { ORGANIZATION_ENRICHMENT_CONFIG, REDIS_CONFIG } from '../../../../conf' import getUserContext from '../../../../database/utils/getUserContext' -import { PLAN_LIMITS } from '../../../../feature-flags/isFeatureEnabled' import OrganizationEnrichmentService from '../../../../services/premium/enrichment/organizationEnrichmentService' export async function BulkorganizationEnrichmentWorker( diff --git a/backend/src/serverless/microservices/nodejs/csv-export/csvExportWorker.ts b/backend/src/serverless/microservices/nodejs/csv-export/csvExportWorker.ts index 0d1e77eee2..768ea45f1d 100644 --- a/backend/src/serverless/microservices/nodejs/csv-export/csvExportWorker.ts +++ b/backend/src/serverless/microservices/nodejs/csv-export/csvExportWorker.ts @@ -6,10 +6,11 @@ import { Hash } from '@aws-sdk/hash-node' import { parseUrl } from '@aws-sdk/url-parser' import { formatUrl } from '@aws-sdk/util-format-url' import { getServiceChildLogger } from '@crowd/logging' +import { ExportableEntity } from '@crowd/types' import getUserContext from '../../../../database/utils/getUserContext' import EmailSender from '../../../../services/emailSender' import { S3_CONFIG } from '../../../../conf' -import { BaseOutput, ExportableEntity } from '../messageTypes' +import { BaseOutput } from '../messageTypes' import getStage from '../../../../services/helpers/getStage' import { s3 } from '../../../../services/aws' import MemberService from '../../../../services/memberService' diff --git a/backend/src/serverless/microservices/nodejs/merge-suggestions/mergeSuggestionsWorker.ts b/backend/src/serverless/microservices/nodejs/merge-suggestions/mergeSuggestionsWorker.ts index 295b2ef6c3..6d47fbbdb5 100644 --- a/backend/src/serverless/microservices/nodejs/merge-suggestions/mergeSuggestionsWorker.ts +++ b/backend/src/serverless/microservices/nodejs/merge-suggestions/mergeSuggestionsWorker.ts @@ -1,6 +1,6 @@ import { getOpensearchClient } from '@crowd/opensearch' import { getServiceChildLogger } from '@crowd/logging' -import { OrganizationMergeSuggestionType } from '@crowd/types' +import { FeatureFlag, OrganizationMergeSuggestionType } from '@crowd/types' import getUserContext from '../../../../database/utils/getUserContext' import MemberService from '../../../../services/memberService' import { IRepositoryOptions } from '../../../../database/repositories/IRepositoryOptions' @@ -11,6 +11,7 @@ import { import SegmentService from '../../../../services/segmentService' import OrganizationService from '@/services/organizationService' import { OPENSEARCH_CONFIG } from '@/conf' +import isFeatureEnabled from '../../../../feature-flags/isFeatureEnabled' const log = getServiceChildLogger('mergeSuggestionsWorker') @@ -30,21 +31,27 @@ async function mergeSuggestionsWorker(tenantId): Promise { log.info(`Generating member merge suggestions for tenant ${tenantId}!`) - const memberService = new MemberService(userContext) - // Splitting these because in the near future we will be treating them differently - const byUsername: IMemberMergeSuggestion[] = await memberService.getMergeSuggestions( - IMemberMergeSuggestionsType.USERNAME, - ) - await memberService.addToMerge(byUsername) - const byEmail: IMemberMergeSuggestion[] = await memberService.getMergeSuggestions( - IMemberMergeSuggestionsType.EMAIL, - ) - await memberService.addToMerge(byEmail) - const bySimilarity: IMemberMergeSuggestion[] = await memberService.getMergeSuggestions( - IMemberMergeSuggestionsType.SIMILARITY, - ) - await memberService.addToMerge(bySimilarity) - log.info(`Done generating member merge suggestions for tenant ${tenantId}!`) + if (isFeatureEnabled(FeatureFlag.TEMPORAL_MEMBER_MERGE_SUGGESTIONS, userContext)) { + log.info( + `Feature flag TEMPORAL_MEMBER_MERGE_SUGGESTIONS is enabled for tenant ${tenantId} - merge suggestions will be generated by temporal, skipping processing in nodejs-worker!`, + ) + } else { + const memberService = new MemberService(userContext) + // Splitting these because in the near future we will be treating them differently + const byUsername: IMemberMergeSuggestion[] = await memberService.getMergeSuggestions( + IMemberMergeSuggestionsType.USERNAME, + ) + await memberService.addToMerge(byUsername) + const byEmail: IMemberMergeSuggestion[] = await memberService.getMergeSuggestions( + IMemberMergeSuggestionsType.EMAIL, + ) + await memberService.addToMerge(byEmail) + const bySimilarity: IMemberMergeSuggestion[] = await memberService.getMergeSuggestions( + IMemberMergeSuggestionsType.SIMILARITY, + ) + await memberService.addToMerge(bySimilarity) + log.info(`Done generating member merge suggestions for tenant ${tenantId}!`) + } } export { mergeSuggestionsWorker } diff --git a/backend/src/serverless/microservices/nodejs/messageTypes.ts b/backend/src/serverless/microservices/nodejs/messageTypes.ts index 30b9aa44dc..acf34ad08b 100644 --- a/backend/src/serverless/microservices/nodejs/messageTypes.ts +++ b/backend/src/serverless/microservices/nodejs/messageTypes.ts @@ -1,4 +1,4 @@ -import { AutomationTrigger, AutomationType } from '@crowd/types' +import { AutomationTrigger, AutomationType, ExportableEntity } from '@crowd/types' export type BaseNodeMicroserviceMessage = { service: string @@ -68,10 +68,6 @@ export interface AnalyticsEmailsOutput extends BaseOutput { emailSent: boolean } -export enum ExportableEntity { - MEMBERS = 'members', -} - export type BulkEnrichMessage = { service: string tenant: string diff --git a/backend/src/serverless/microservices/nodejs/org-merge/orgMergeWorker.ts b/backend/src/serverless/microservices/nodejs/org-merge/orgMergeWorker.ts deleted file mode 100644 index 747927ddd2..0000000000 --- a/backend/src/serverless/microservices/nodejs/org-merge/orgMergeWorker.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { getRedisClient, RedisPubSubEmitter } from '@crowd/redis' -import { ApiWebsocketMessage } from '@crowd/types' -import { REDIS_CONFIG } from '../../../../conf' -import getUserContext from '../../../../database/utils/getUserContext' -import OrganizationService from '../../../../services/organizationService' - -async function doNotifyFrontend({ log, success, tenantId, primaryOrgId, secondaryOrgId }) { - const redis = await getRedisClient(REDIS_CONFIG, true) - const apiPubSubEmitter = new RedisPubSubEmitter( - 'api-pubsub', - redis, - (err) => { - log.error({ err }, 'Error in api-ws emitter!') - }, - log, - ) - - apiPubSubEmitter.emit( - 'user', - new ApiWebsocketMessage( - 'org-merge', - JSON.stringify({ - success, - tenantId, - primaryOrgId, - secondaryOrgId, - }), - undefined, - tenantId, - ), - ) -} - -async function orgMergeWorker( - tenantId: string, - primaryOrgId: string, - secondaryOrgId: string, - notifyFrontend: boolean, -) { - const userContext = await getUserContext(tenantId) - - const organizationService = new OrganizationService(userContext) - - let success = true - try { - await organizationService.mergeSync(primaryOrgId, secondaryOrgId) - } catch (err) { - userContext.log.error(err, 'Error merging orgs') - success = false - } - - if (notifyFrontend) { - await doNotifyFrontend({ - log: userContext.log, - success, - tenantId, - primaryOrgId, - secondaryOrgId, - }) - } -} -export { orgMergeWorker } diff --git a/backend/src/serverless/microservices/nodejs/workerFactory.ts b/backend/src/serverless/microservices/nodejs/workerFactory.ts index d1f7ca1c97..4222403eb6 100644 --- a/backend/src/serverless/microservices/nodejs/workerFactory.ts +++ b/backend/src/serverless/microservices/nodejs/workerFactory.ts @@ -5,7 +5,6 @@ import { BulkEnrichMessage, IntegrationDataCheckerMessage, OrganizationBulkEnrichMessage, - OrganizationMergeMessage, } from './messageTypes' import { csvExportWorker } from './csv-export/csvExportWorker' import { processStripeWebhook } from '../../integrations/workers/stripeWebhookWorker' @@ -14,7 +13,6 @@ import { bulkEnrichmentWorker } from './bulk-enrichment/bulkEnrichmentWorker' import { integrationDataCheckerWorker } from './integration-data-checker/integrationDataCheckerWorker' import { refreshSampleDataWorker } from './integration-data-checker/refreshSampleDataWorker' import { mergeSuggestionsWorker } from './merge-suggestions/mergeSuggestionsWorker' -import { orgMergeWorker } from './org-merge/orgMergeWorker' import { BulkorganizationEnrichmentWorker } from './bulk-enrichment/bulkOrganizationEnrichmentWorker' /** @@ -69,14 +67,6 @@ async function workerFactory(event: NodeMicroserviceMessage): Promise { bulkEnrichMessage.maxEnrichLimit, ) } - case 'org-merge': - const orgMergeMessage = event as OrganizationMergeMessage - return orgMergeWorker( - orgMergeMessage.tenantId, - orgMergeMessage.primaryOrgId, - orgMergeMessage.secondaryOrgId, - orgMergeMessage.notifyFrontend, - ) default: throw new Error(`Invalid microservice ${service}`) diff --git a/backend/src/serverless/types/workerTypes.ts b/backend/src/serverless/types/workerTypes.ts index 9ab75a0917..91c9bc3dbd 100644 --- a/backend/src/serverless/types/workerTypes.ts +++ b/backend/src/serverless/types/workerTypes.ts @@ -1,9 +1,7 @@ export enum NodeWorkerMessageType { INTEGRATION_CHECK = 'integration_check', - INTEGRATION_PROCESS = 'integration_process', NODE_MICROSERVICE = 'node_microservice', DB_OPERATIONS = 'db_operations', - PROCESS_WEBHOOK = 'process_webhook', } export enum PythonWorkerMessageType { diff --git a/backend/src/serverless/utils/nodeWorkerSQS.ts b/backend/src/serverless/utils/nodeWorkerSQS.ts deleted file mode 100644 index 0bbe22ddd7..0000000000 --- a/backend/src/serverless/utils/nodeWorkerSQS.ts +++ /dev/null @@ -1,171 +0,0 @@ -import { getServiceChildLogger } from '@crowd/logging' -import { SqsMessageAttributes, sendMessage } from '@crowd/sqs' -import { AutomationTrigger } from '@crowd/types' -import moment from 'moment' -import { IS_TEST_ENV, SQS_CONFIG } from '../../conf' -import { NodeWorkerMessageBase } from '../../types/mq/nodeWorkerMessageBase' -import { ExportableEntity } from '../microservices/nodejs/messageTypes' -import { NodeWorkerMessageType } from '../types/workerTypes' -import { SQS_CLIENT } from './serviceSQS' - -const log = getServiceChildLogger('nodeWorkerSQS') - -// 15 minute limit for delaying is max for SQS -const limitSeconds = 15 * 60 - -export const sendNodeWorkerMessage = async ( - tenantId: string, - body: NodeWorkerMessageBase, - delaySeconds?: number, - targetQueueUrl?: string, -): Promise => { - if (IS_TEST_ENV) { - return - } - - // we can only delay for 15 minutes then we have to re-delay message - let attributes: SqsMessageAttributes - let delay: number - let delayed = false - if (delaySeconds) { - if (delaySeconds > limitSeconds) { - // delay for 15 minutes and add the remaineder to the attributes - const remainedSeconds = delaySeconds - limitSeconds - attributes = { - tenantId: { - DataType: 'String', - StringValue: tenantId, - }, - remainingDelaySeconds: { - DataType: 'Number', - StringValue: `${remainedSeconds}`, - }, - } - - if (targetQueueUrl) { - attributes.targetQueueUrl = { DataType: 'String', StringValue: targetQueueUrl } - } - delay = limitSeconds - } else { - attributes = { - tenantId: { - DataType: 'String', - StringValue: tenantId, - }, - } - if (targetQueueUrl) { - attributes.targetQueueUrl = { DataType: 'String', StringValue: targetQueueUrl } - } - delay = delaySeconds - } - - delayed = true - } - - const now = moment().valueOf() - - const params = { - QueueUrl: delayed ? SQS_CONFIG.nodejsWorkerDelayableQueue : SQS_CONFIG.nodejsWorkerQueue, - MessageGroupId: delayed ? undefined : `${now}`, - MessageDeduplicationId: delayed ? undefined : `${tenantId}-${now}`, - MessageBody: JSON.stringify(body), - MessageAttributes: attributes, - DelaySeconds: delay, - } - - log.debug( - { - messageType: body.type, - body, - }, - 'Sending nodejs-worker sqs message!', - ) - await sendMessage(SQS_CLIENT(), params) -} - -export const sendNewActivityNodeSQSMessage = async ( - tenant: string, - activityId: string, - segmentId: string, -): Promise => { - const payload = { - type: NodeWorkerMessageType.NODE_MICROSERVICE, - tenant, - activityId, - segmentId, - trigger: AutomationTrigger.NEW_ACTIVITY, - service: 'automation', - } - await sendNodeWorkerMessage(tenant, payload as NodeWorkerMessageBase) -} - -export const sendNewMemberNodeSQSMessage = async ( - tenant: string, - memberId: string, - segmentId: string, -): Promise => { - const payload = { - type: NodeWorkerMessageType.NODE_MICROSERVICE, - tenant, - memberId, - segmentId, - trigger: AutomationTrigger.NEW_MEMBER, - service: 'automation', - } - await sendNodeWorkerMessage(tenant, payload as NodeWorkerMessageBase) -} - -export const sendExportCSVNodeSQSMessage = async ( - tenant: string, - user: string, - entity: ExportableEntity, - segmentIds: string[], - criteria: any, -): Promise => { - const payload = { - type: NodeWorkerMessageType.NODE_MICROSERVICE, - service: 'csv-export', - user, - tenant, - entity, - criteria, - segmentIds, - } - await sendNodeWorkerMessage(tenant, payload as NodeWorkerMessageBase) -} - -export const sendBulkEnrichMessage = async ( - tenant: string, - memberIds: string[], - segmentIds: string[], - notifyFrontend: boolean = true, - skipCredits: boolean = false, -): Promise => { - const payload = { - type: NodeWorkerMessageType.NODE_MICROSERVICE, - service: 'bulk-enrich', - memberIds, - tenant, - segmentIds, - notifyFrontend, - skipCredits, - } - await sendNodeWorkerMessage(tenant, payload as NodeWorkerMessageBase) -} - -export const sendOrgMergeMessage = async ( - tenantId: string, - primaryOrgId: string, - secondaryOrgId: string, - notifyFrontend: boolean = true, -): Promise => { - const payload = { - type: NodeWorkerMessageType.NODE_MICROSERVICE, - service: 'org-merge', - tenantId, - primaryOrgId, - secondaryOrgId, - notifyFrontend, - } - await sendNodeWorkerMessage(tenantId, payload as NodeWorkerMessageBase) -} diff --git a/backend/src/serverless/utils/serviceSQS.ts b/backend/src/serverless/utils/serviceSQS.ts index 2f25f478b2..cfdf20d01c 100644 --- a/backend/src/serverless/utils/serviceSQS.ts +++ b/backend/src/serverless/utils/serviceSQS.ts @@ -1,15 +1,20 @@ +import { SqsClient, getSqsClient } from '@crowd/sqs' +import { getServiceChildLogger } from '@crowd/logging' +import { getServiceTracer } from '@crowd/tracing' import { IntegrationRunWorkerEmitter, IntegrationStreamWorkerEmitter, - IntegrationSyncWorkerEmitter, SearchSyncWorkerEmitter, DataSinkWorkerEmitter, - SqsClient, - getSqsClient, -} from '@crowd/sqs' -import { getServiceChildLogger } from '@crowd/logging' -import { getServiceTracer } from '@crowd/tracing' -import { SQS_CONFIG } from '../../conf' + IntegrationSyncWorkerEmitter, + QueuePriorityContextLoader, + NodejsWorkerEmitter, +} from '@crowd/common_services' +import { UnleashClient, getUnleashClient } from '@crowd/feature-flags' +import { RedisClient, getRedisClient } from '@crowd/redis' +import { REDIS_CONFIG, SERVICE, SQS_CONFIG, UNLEASH_CONFIG } from '../../conf' +import SequelizeRepository from '@/database/repositories/sequelizeRepository' +import { PriorityLevelContextRepository } from '@/database/repositories/priorityLevelContextRepository' const tracer = getServiceTracer() const log = getServiceChildLogger('service.sqs') @@ -29,11 +34,58 @@ export const SQS_CLIENT = (): SqsClient => { return sqsClient } +let unleashClient: UnleashClient | undefined +let unleashClientInitialized = false +const UNLEASH_CLIENT = async (): Promise => { + if (unleashClientInitialized) { + return unleashClient + } + + unleashClient = await getUnleashClient({ + url: UNLEASH_CONFIG.url, + apiKey: UNLEASH_CONFIG.backendApiKey, + appName: SERVICE, + }) + unleashClientInitialized = true + return unleashClient +} + +let redisClient: RedisClient +const REDIS_CLIENT = async (): Promise => { + if (redisClient) { + return redisClient + } + + redisClient = await getRedisClient(REDIS_CONFIG, true) + + return redisClient +} + +let loader: QueuePriorityContextLoader +export const QUEUE_PRIORITY_LOADER = async (): Promise => { + if (loader) { + return loader + } + + const options = await SequelizeRepository.getDefaultIRepositoryOptions() + const repo = new PriorityLevelContextRepository(options) + + loader = (tenantId: string) => repo.loadPriorityLevelContext(tenantId) + return loader +} + let runWorkerEmitter: IntegrationRunWorkerEmitter export const getIntegrationRunWorkerEmitter = async (): Promise => { if (runWorkerEmitter) return runWorkerEmitter - runWorkerEmitter = new IntegrationRunWorkerEmitter(SQS_CLIENT(), tracer, log) + runWorkerEmitter = new IntegrationRunWorkerEmitter( + SQS_CLIENT(), + await REDIS_CLIENT(), + tracer, + await UNLEASH_CLIENT(), + await QUEUE_PRIORITY_LOADER(), + log, + ) await runWorkerEmitter.init() return runWorkerEmitter } @@ -43,7 +95,14 @@ export const getIntegrationStreamWorkerEmitter = async (): Promise => { if (streamWorkerEmitter) return streamWorkerEmitter - streamWorkerEmitter = new IntegrationStreamWorkerEmitter(SQS_CLIENT(), tracer, log) + streamWorkerEmitter = new IntegrationStreamWorkerEmitter( + SQS_CLIENT(), + await REDIS_CLIENT(), + tracer, + await UNLEASH_CLIENT(), + await QUEUE_PRIORITY_LOADER(), + log, + ) await streamWorkerEmitter.init() return streamWorkerEmitter } @@ -52,7 +111,14 @@ let searchSyncWorkerEmitter: SearchSyncWorkerEmitter export const getSearchSyncWorkerEmitter = async (): Promise => { if (searchSyncWorkerEmitter) return searchSyncWorkerEmitter - searchSyncWorkerEmitter = new SearchSyncWorkerEmitter(SQS_CLIENT(), tracer, log) + searchSyncWorkerEmitter = new SearchSyncWorkerEmitter( + SQS_CLIENT(), + await REDIS_CLIENT(), + tracer, + await UNLEASH_CLIENT(), + await QUEUE_PRIORITY_LOADER(), + log, + ) await searchSyncWorkerEmitter.init() return searchSyncWorkerEmitter } @@ -61,7 +127,14 @@ let integrationSyncWorkerEmitter: IntegrationSyncWorkerEmitter export const getIntegrationSyncWorkerEmitter = async (): Promise => { if (integrationSyncWorkerEmitter) return integrationSyncWorkerEmitter - integrationSyncWorkerEmitter = new IntegrationSyncWorkerEmitter(SQS_CLIENT(), tracer, log) + integrationSyncWorkerEmitter = new IntegrationSyncWorkerEmitter( + SQS_CLIENT(), + await REDIS_CLIENT(), + tracer, + await UNLEASH_CLIENT(), + await QUEUE_PRIORITY_LOADER(), + log, + ) await integrationSyncWorkerEmitter.init() return integrationSyncWorkerEmitter } @@ -70,7 +143,30 @@ let dataSinkWorkerEmitter: DataSinkWorkerEmitter export const getDataSinkWorkerEmitter = async (): Promise => { if (dataSinkWorkerEmitter) return dataSinkWorkerEmitter - dataSinkWorkerEmitter = new DataSinkWorkerEmitter(SQS_CLIENT(), tracer, log) + dataSinkWorkerEmitter = new DataSinkWorkerEmitter( + SQS_CLIENT(), + await REDIS_CLIENT(), + tracer, + await UNLEASH_CLIENT(), + await QUEUE_PRIORITY_LOADER(), + log, + ) await dataSinkWorkerEmitter.init() return dataSinkWorkerEmitter } + +let nodejsWorkerEmitter: NodejsWorkerEmitter +export const getNodejsWorkerEmitter = async (): Promise => { + if (nodejsWorkerEmitter) return nodejsWorkerEmitter + + nodejsWorkerEmitter = new NodejsWorkerEmitter( + SQS_CLIENT(), + await REDIS_CLIENT(), + tracer, + await UNLEASH_CLIENT(), + await QUEUE_PRIORITY_LOADER(), + log, + ) + await nodejsWorkerEmitter.init() + return nodejsWorkerEmitter +} diff --git a/backend/src/services/__tests__/activityService.test.ts b/backend/src/services/__tests__/activityService.test.ts deleted file mode 100644 index 72edf61759..0000000000 --- a/backend/src/services/__tests__/activityService.test.ts +++ /dev/null @@ -1,3193 +0,0 @@ -import { v4 as uuid } from 'uuid' - -import SequelizeTestUtils from '../../database/utils/sequelizeTestUtils' -import MemberService from '../memberService' -import ActivityService from '../activityService' -import MemberRepository from '../../database/repositories/memberRepository' -import ActivityRepository from '../../database/repositories/activityRepository' -import ConversationService from '../conversationService' -import SequelizeRepository from '../../database/repositories/sequelizeRepository' -import { MemberAttributeName, PlatformType, SegmentStatus } from '@crowd/types' -import SettingsRepository from '../../database/repositories/settingsRepository' -import ConversationSettingsRepository from '../../database/repositories/conversationSettingsRepository' -import MemberAttributeSettingsService from '../memberAttributeSettingsService' -import { IServiceOptions } from '../../services/IServiceOptions' -import { GITHUB_MEMBER_ATTRIBUTES, TWITTER_MEMBER_ATTRIBUTES } from '@crowd/integrations' -import { populateSegments, switchSegments } from '../../database/utils/segmentTestUtils' -import SegmentRepository from '../../database/repositories/segmentRepository' -import OrganizationRepository from '../../database/repositories/organizationRepository' -import OrganizationService from '../organizationService' -import MemberSegmentAffiliationRepository from '../../database/repositories/memberSegmentAffiliationRepository' -import SegmentService from '../segmentService' -import MemberAffiliationService from '../memberAffiliationService' - -const db = null -const searchEngine = null - -describe('ActivityService tests', () => { - beforeEach(async () => { - await SequelizeTestUtils.wipeDatabase(db) - }) - - afterAll(async () => { - // Closing the DB connection allows Jest to exit successfully. - await SequelizeTestUtils.closeConnection(db) - }) - - describe('upsert method', () => { - it('Should create non existent activity with no parent', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - await populateSegments(mockIRepositoryOptions) - - const memberCreated = await new MemberService(mockIRepositoryOptions).upsert({ - username: { - [PlatformType.GITHUB]: 'test', - }, - platform: PlatformType.GITHUB, - joinedAt: '2020-05-27T15:13:30Z', - }) - - const activity = { - type: 'activity', - timestamp: '2020-05-27T15:13:30Z', - platform: PlatformType.GITHUB, - body: 'Body', - title: 'Title', - url: 'URL', - sentiment: { - positive: 0.98, - negative: 0.0, - neutral: 0.02, - mixed: 0.0, - label: 'positive', - sentiment: 0.98, - }, - attributes: { - replies: 12, - }, - sourceId: '#sourceId', - isContribution: true, - username: 'test', - member: memberCreated.id, - score: 1, - } - - const activityCreated = await new ActivityService(mockIRepositoryOptions).upsert(activity) - - // Trim the hour part from timestamp so we can atleast test if the day is correct for createdAt and joinedAt - activityCreated.createdAt = activityCreated.createdAt.toISOString().split('T')[0] - activityCreated.updatedAt = activityCreated.updatedAt.toISOString().split('T')[0] - delete activityCreated.member - delete activityCreated.objectMember - - const expectedActivityCreated = { - id: activityCreated.id, - attributes: activity.attributes, - type: 'activity', - timestamp: new Date('2020-05-27T15:13:30Z'), - platform: PlatformType.GITHUB, - isContribution: true, - score: 1, - username: 'test', - objectMemberUsername: null, - memberId: memberCreated.id, - objectMemberId: null, - createdAt: SequelizeTestUtils.getNowWithoutTime(), - updatedAt: SequelizeTestUtils.getNowWithoutTime(), - deletedAt: null, - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - createdById: mockIRepositoryOptions.currentUser.id, - updatedById: mockIRepositoryOptions.currentUser.id, - importHash: null, - channel: null, - body: 'Body', - title: 'Title', - url: 'URL', - sentiment: { - positive: 0.98, - negative: 0.0, - neutral: 0.02, - mixed: 0.0, - label: 'positive', - sentiment: 0.98, - }, - tasks: [], - parent: null, - parentId: null, - conversationId: null, - sourceId: activity.sourceId, - sourceParentId: null, - display: { - default: activityCreated.type, - short: activityCreated.type, - channel: '', - }, - organizationId: null, - organization: null, - } - - expect(activityCreated).toStrictEqual(expectedActivityCreated) - }) - - it('Should create non existent activity with parent', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - await populateSegments(mockIRepositoryOptions) - const memberCreated = await new MemberService(mockIRepositoryOptions).upsert({ - username: { - [PlatformType.GITHUB]: 'test', - }, - platform: PlatformType.GITHUB, - joinedAt: '2020-05-27T15:13:30Z', - }) - - const activity1 = { - type: 'question', - timestamp: '2020-05-27T15:13:30Z', - username: 'test', - member: memberCreated.id, - platform: 'non-existing-platform', - body: 'What is love?', - isContribution: true, - score: 1, - sourceId: 'sourceId#1', - } - - const activityCreated1 = await new ActivityService(mockIRepositoryOptions).upsert(activity1) - - const activity2 = { - type: 'answer', - timestamp: '2020-05-28T15:13:30Z', - platform: 'non-existing-platform', - body: 'Baby dont hurt me', - isContribution: true, - username: 'test', - member: memberCreated.id, - score: 2, - sourceId: 'sourceId#2', - sourceParentId: activityCreated1.sourceId, - } - - const activityCreated2 = await new ActivityService(mockIRepositoryOptions).upsert(activity2) - - // Since an activity with a parent is created, a Conversation entity should be created at this point - // with both parent and the child activities. Try finding it using the slug - - const conversationCreated = await new ConversationService( - mockIRepositoryOptions, - ).findAndCountAll({ slug: 'what-is-love' }) - - delete activityCreated2.member - delete activityCreated2.parent - delete activityCreated2.objectMember - - // Trim the hour part from timestamp so we can atleast test if the day is correct for createdAt and joinedAt - activityCreated2.createdAt = activityCreated2.createdAt.toISOString().split('T')[0] - activityCreated2.updatedAt = activityCreated2.updatedAt.toISOString().split('T')[0] - - const expectedActivityCreated = { - id: activityCreated2.id, - body: activity2.body, - type: activity2.type, - channel: null, - attributes: {}, - sentiment: { - positive: 0.42, - negative: 0.42, - neutral: 0.42, - mixed: 0.42, - label: 'positive', - sentiment: 0.42, - }, - url: null, - title: null, - timestamp: new Date(activity2.timestamp), - platform: activity2.platform, - isContribution: activity2.isContribution, - score: activity2.score, - username: 'test', - objectMemberUsername: null, - memberId: memberCreated.id, - objectMemberId: null, - tasks: [], - createdAt: SequelizeTestUtils.getNowWithoutTime(), - updatedAt: SequelizeTestUtils.getNowWithoutTime(), - deletedAt: null, - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - createdById: mockIRepositoryOptions.currentUser.id, - updatedById: mockIRepositoryOptions.currentUser.id, - importHash: null, - parentId: activityCreated1.id, - sourceParentId: activity1.sourceId, - sourceId: activity2.sourceId, - conversationId: conversationCreated.rows[0].id, - display: { - default: activity2.type, - short: activity2.type, - channel: '', - }, - organizationId: null, - organization: null, - } - - expect(activityCreated2).toStrictEqual(expectedActivityCreated) - }) - - it('Should update already existing activity succesfully', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - await populateSegments(mockIRepositoryOptions) - const memberCreated = await new MemberService(mockIRepositoryOptions).upsert({ - username: { - [PlatformType.GITHUB]: 'test', - }, - platform: PlatformType.GITHUB, - joinedAt: '2020-05-27T15:13:30Z', - }) - - const activity1 = { - type: 'question', - timestamp: '2020-05-27T15:13:30Z', - username: 'test', - member: memberCreated.id, - body: 'What is love?', - title: 'Song', - platform: 'non-existing-platform', - attributes: { - nested_1: { - attribute_1: '1', - nested_2: { - attribute_2: '2', - attribute_array: [1, 2, 3], - }, - }, - }, - isContribution: true, - score: 1, - sourceId: '#sourceId1', - } - - const activityCreated1 = await new ActivityService(mockIRepositoryOptions).upsert(activity1) - - const activity2 = { - type: 'question', - timestamp: '2020-05-27T15:13:30Z', - username: 'test', - member: memberCreated.id, - platform: 'non-existing-platform', - body: 'Test', - attributes: { - nested_1: { - attribute_1: '1', - nested_2: { - attribute_2: '5', - attribute_3: 'test', - attribute_array: [3, 4, 5], - }, - }, - one: 'Baby dont hurt me', - two: 'Dont hurt me', - three: 'No more', - }, - isContribution: false, - score: 2, - sourceId: '#sourceId1', - } - - const activityUpserted = await new ActivityService(mockIRepositoryOptions).upsert(activity2) - - // Trim the hour part from timestamp so we can atleast test if the day is correct for createdAt and joinedAt - activityUpserted.createdAt = activityUpserted.createdAt.toISOString().split('T')[0] - activityUpserted.updatedAt = activityUpserted.updatedAt.toISOString().split('T')[0] - - // delete models before expect because we already have ids (memberId, parentId) - delete activityUpserted.member - delete activityUpserted.parent - delete activityUpserted.objectMember - - const attributesExpected = { - ...activity1.attributes, - ...activity2.attributes, - } - - attributesExpected.nested_1.nested_2.attribute_array = [1, 2, 3, 4, 5] - - const expectedActivityCreated = { - id: activityCreated1.id, - attributes: attributesExpected, - type: activity2.type, - timestamp: new Date(activity2.timestamp), - platform: activity2.platform, - isContribution: activity2.isContribution, - score: activity2.score, - title: activity1.title, - sentiment: { - positive: 0.42, - negative: 0.42, - neutral: 0.42, - mixed: 0.42, - label: 'positive', - sentiment: 0.42, - }, - url: null, - body: activity2.body, - channel: null, - username: 'test', - objectMemberUsername: null, - memberId: memberCreated.id, - objectMemberId: null, - createdAt: SequelizeTestUtils.getNowWithoutTime(), - updatedAt: SequelizeTestUtils.getNowWithoutTime(), - tasks: [], - deletedAt: null, - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - createdById: mockIRepositoryOptions.currentUser.id, - updatedById: mockIRepositoryOptions.currentUser.id, - importHash: null, - parentId: null, - sourceParentId: null, - sourceId: activity1.sourceId, - conversationId: null, - display: { - default: activity2.type, - short: activity2.type, - channel: '', - }, - organizationId: null, - organization: null, - } - - expect(activityUpserted).toStrictEqual(expectedActivityCreated) - }) - - it('Should create various conversations successfully with given parent-child relationships of activities [ascending timestamp order]', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - await populateSegments(mockIRepositoryOptions) - const memberService = new MemberService(mockIRepositoryOptions) - const activityService = new ActivityService(mockIRepositoryOptions) - - const member1Created = await memberService.upsert({ - username: { - [PlatformType.DISCORD]: 'test', - }, - platform: PlatformType.DISCORD, - joinedAt: '2020-05-27T15:13:30Z', - }) - const member2Created = await memberService.upsert({ - username: { - [PlatformType.DISCORD]: 'test2', - }, - platform: PlatformType.DISCORD, - joinedAt: '2020-05-27T15:13:30Z', - }) - - // Simulate a reply chain in discord - - const activity1 = { - type: 'message', - timestamp: '2020-05-27T15:13:30Z', - username: 'test', - member: member1Created.id, - platform: PlatformType.DISCORD, - body: 'What is love?', - isContribution: true, - score: 1, - sourceId: 'sourceId#1', - } - - let activityCreated1 = await activityService.upsert(activity1) - - const activity2 = { - type: 'message', - timestamp: '2020-05-28T15:14:30Z', - platform: PlatformType.DISCORD, - body: 'Baby dont hurt me', - isContribution: true, - username: 'test2', - member: member2Created.id, - score: 2, - sourceId: 'sourceId#2', - sourceParentId: activityCreated1.sourceId, - } - - const activityCreated2 = await activityService.upsert(activity2) - - const activity3 = { - type: 'message', - timestamp: '2020-05-28T15:15:30Z', - platform: PlatformType.DISCORD, - body: 'Dont hurt me', - isContribution: true, - username: 'test', - member: member1Created.id, - score: 2, - sourceId: 'sourceId#3', - sourceParentId: activityCreated2.sourceId, - } - - const activityCreated3 = await activityService.upsert(activity3) - - const activity4 = { - type: 'message', - timestamp: '2020-05-28T15:16:30Z', - platform: PlatformType.DISCORD, - body: 'No more', - isContribution: true, - username: 'test2', - member: member2Created.id, - score: 2, - sourceId: 'sourceId#4', - sourceParentId: activityCreated3.sourceId, - } - - const activityCreated4 = await activityService.upsert(activity4) - - // Get the conversation using slug (generated using the chain starter activity attributes.body) - const conversationCreated = ( - await new ConversationService(mockIRepositoryOptions).findAndCountAll({ - slug: 'what-is-love', - }) - ).rows[0] - - // We have to get activity1 again because conversation creation happens - // after creation of the first activity that has a parent (activity2) - activityCreated1 = await activityService.findById(activityCreated1.id) - - // All activities (including chain starter) should belong to the same conversation - expect(activityCreated1.conversationId).toStrictEqual(conversationCreated.id) - expect(activityCreated2.conversationId).toStrictEqual(conversationCreated.id) - expect(activityCreated3.conversationId).toStrictEqual(conversationCreated.id) - expect(activityCreated4.conversationId).toStrictEqual(conversationCreated.id) - - // Emulate a thread in discord - - const activity5 = { - type: 'message', - timestamp: '2020-05-28T15:17:30Z', - platform: PlatformType.DISCORD, - body: 'Never gonna give you up', - isContribution: true, - username: 'test', - member: member1Created.id, - score: 2, - sourceId: 'sourceId#5', - } - let activityCreated5 = await activityService.upsert(activity5) - - const activity6 = { - type: 'message', - timestamp: '2020-05-28T15:18:30Z', - platform: PlatformType.DISCORD, - body: 'Never gonna let you down', - isContribution: true, - username: 'test2', - member: member2Created.id, - score: 2, - sourceId: 'sourceId#6', - sourceParentId: activityCreated5.sourceId, - } - const activityCreated6 = await activityService.upsert(activity6) - - const activity7 = { - type: 'message', - timestamp: '2020-05-28T15:19:30Z', - platform: PlatformType.DISCORD, - body: 'Never gonna run around and desert you', - isContribution: true, - username: 'test', - member: member1Created.id, - score: 2, - sourceId: 'sourceId#7', - sourceParentId: activityCreated5.sourceId, - } - const activityCreated7 = await activityService.upsert(activity7) - - const conversationCreated2 = ( - await new ConversationService(mockIRepositoryOptions).findAndCountAll({ - slug: 'never-gonna-give-you-up', - }) - ).rows[0] - - activityCreated5 = await activityService.findById(activityCreated5.id) - - // All activities (including thread starter) should belong to the same conversation - expect(activityCreated5.conversationId).toStrictEqual(conversationCreated2.id) - expect(activityCreated6.conversationId).toStrictEqual(conversationCreated2.id) - expect(activityCreated7.conversationId).toStrictEqual(conversationCreated2.id) - }) - - it('Should keep old timestamp', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - await populateSegments(mockIRepositoryOptions) - const memberService = new MemberService(mockIRepositoryOptions) - const activityService = new ActivityService(mockIRepositoryOptions) - - const cm = await memberService.upsert({ - username: { - [PlatformType.DISCORD]: 'test', - }, - platform: PlatformType.DISCORD, - }) - - const activity1 = { - type: 'message', - timestamp: '2020-05-27T15:13:30Z', - username: 'test', - member: cm.id, - platform: PlatformType.DISCORD, - sourceId: 'sourceId#1', - } - - const activityCreated1 = await activityService.upsert(activity1) - - const activity2 = { - type: 'message', - timestamp: '2022-05-27T15:13:30Z', - username: 'test', - member: cm.id, - platform: PlatformType.DISCORD, - sourceId: 'sourceId#1', - body: 'What is love?', - } - - const activityCreated2 = await activityService.upsert(activity2) - - expect(activityCreated2.timestamp).toStrictEqual(activityCreated1.timestamp) - expect(activityCreated2.body).toBe(activity2.body) - }) - - it('Should keep isMainBranch as true', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - await populateSegments(mockIRepositoryOptions) - const memberService = new MemberService(mockIRepositoryOptions) - const activityService = new ActivityService(mockIRepositoryOptions) - - const cm = await memberService.upsert({ - username: { - [PlatformType.DISCORD]: 'test', - }, - platform: PlatformType.DISCORD, - }) - - const activity1 = { - type: 'message', - timestamp: '2020-05-27T15:13:30Z', - username: 'test', - member: cm.id, - platform: PlatformType.DISCORD, - sourceId: 'sourceId#1', - attributes: { - isMainBranch: true, - other: 'other', - }, - } - - await activityService.upsert(activity1) - - const activity2 = { - type: 'message', - timestamp: '2022-05-27T15:13:30Z', - username: 'test', - member: cm.id, - platform: PlatformType.DISCORD, - sourceId: 'sourceId#1', - body: 'What is love?', - attributes: { - isMainBranch: false, - other2: 'other2', - }, - } - - const activityCreated2 = await activityService.upsert(activity2) - - expect(activityCreated2.attributes).toStrictEqual({ - isMainBranch: true, - other: 'other', - other2: 'other2', - }) - }) - - it('Should create various conversations successfully with given parent-child relationships of activities [descending timestamp order]', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - await populateSegments(mockIRepositoryOptions) - const memberService = new MemberService(mockIRepositoryOptions) - const activityService = new ActivityService(mockIRepositoryOptions) - - const member1Created = await memberService.upsert({ - username: { - [PlatformType.DISCORD]: 'test', - }, - platform: PlatformType.DISCORD, - joinedAt: '2020-05-27T15:13:30Z', - }) - - const member2Created = await memberService.upsert({ - username: { - [PlatformType.DISCORD]: 'test2', - }, - platform: PlatformType.DISCORD, - joinedAt: '2020-05-27T15:13:30Z', - }) - - // Simulate a reply chain in discord in reverse order (child activities come first) - - const activity4 = { - type: 'message', - timestamp: '2020-05-28T15:16:30Z', - platform: PlatformType.DISCORD, - body: 'No more', - isContribution: true, - username: 'test2', - member: member2Created.id, - score: 2, - sourceId: 'sourceId#4', - sourceParentId: 'sourceId#3', - } - - let activityCreated4 = await activityService.upsert(activity4) - - const activity3 = { - type: 'message', - timestamp: '2020-05-28T15:15:30Z', - platform: PlatformType.DISCORD, - body: 'Dont hurt me', - isContribution: true, - username: 'test', - member: member1Created.id, - score: 2, - sourceId: 'sourceId#3', - sourceParentId: 'sourceId#2', - } - - let activityCreated3 = await activityService.upsert(activity3) - - const activity2 = { - type: 'message', - timestamp: '2020-05-28T15:14:30Z', - platform: PlatformType.DISCORD, - body: 'Baby dont hurt me', - isContribution: true, - username: 'test2', - member: member2Created.id, - score: 2, - sourceId: 'sourceId#2', - sourceParentId: 'sourceId#1', - } - - let activityCreated2 = await activityService.upsert(activity2) - - const activity1 = { - type: 'message', - timestamp: '2020-05-27T15:13:30Z', - username: 'test', - member: member1Created.id, - platform: PlatformType.DISCORD, - body: 'What is love?', - isContribution: true, - score: 1, - sourceId: 'sourceId#1', - } - - // main parent activity that starts the reply chain - let activityCreated1 = await activityService.upsert(activity1) - - // get activities again - activityCreated1 = await activityService.findById(activityCreated1.id) - activityCreated2 = await activityService.findById(activityCreated2.id) - activityCreated3 = await activityService.findById(activityCreated3.id) - activityCreated4 = await activityService.findById(activityCreated4.id) - - // expect parentIds - expect(activityCreated4.parentId).toBe(activityCreated3.id) - expect(activityCreated3.parentId).toBe(activityCreated2.id) - expect(activityCreated2.parentId).toBe(activityCreated1.id) - - // Get the conversation using slug (generated using the chain starter activity attributes.body -last added activityCreated1-) - const conversationCreated = ( - await new ConversationService(mockIRepositoryOptions).findAndCountAll({ - slug: 'what-is-love', - }) - ).rows[0] - - // All activities (including chain starter) should belong to the same conversation - expect(activityCreated1.conversationId).toStrictEqual(conversationCreated.id) - expect(activityCreated2.conversationId).toStrictEqual(conversationCreated.id) - expect(activityCreated3.conversationId).toStrictEqual(conversationCreated.id) - expect(activityCreated4.conversationId).toStrictEqual(conversationCreated.id) - - // Simulate a thread in reverse order - - const activity6 = { - type: 'message', - timestamp: '2020-05-28T15:18:30Z', - platform: PlatformType.DISCORD, - body: 'Never gonna let you down', - isContribution: true, - username: 'test2', - member: member2Created.id, - score: 2, - sourceId: 'sourceId#6', - sourceParentId: 'sourceId#5', - } - let activityCreated6 = await activityService.upsert(activity6) - - const activity7 = { - type: 'message', - timestamp: '2020-05-28T15:19:30Z', - platform: PlatformType.DISCORD, - body: 'Never gonna run around and desert you', - - isContribution: true, - username: 'test', - member: member1Created.id, - score: 2, - sourceId: 'sourceId#7', - sourceParentId: 'sourceId#5', - } - let activityCreated7 = await activityService.upsert(activity7) - - const activity5 = { - type: 'message', - timestamp: '2020-05-28T15:17:30Z', - platform: PlatformType.DISCORD, - body: 'Never gonna give you up', - isContribution: true, - username: 'test', - member: member1Created.id, - score: 2, - sourceId: 'sourceId#5', - } - let activityCreated5 = await activityService.upsert(activity5) - - const conversationCreated2 = ( - await new ConversationService(mockIRepositoryOptions).findAndCountAll({ - slug: 'never-gonna-give-you-up', - }) - ).rows[0] - - // get activities again - activityCreated5 = await activityService.findById(activityCreated5.id) - activityCreated6 = await activityService.findById(activityCreated6.id) - activityCreated7 = await activityService.findById(activityCreated7.id) - - // expect parentIds - expect(activityCreated6.parentId).toBe(activityCreated5.id) - expect(activityCreated7.parentId).toBe(activityCreated5.id) - - expect(activityCreated5.conversationId).toStrictEqual(conversationCreated2.id) - expect(activityCreated6.conversationId).toStrictEqual(conversationCreated2.id) - expect(activityCreated7.conversationId).toStrictEqual(conversationCreated2.id) - - // Add some more childs to the conversation1 and conversation2 - // After setting child-parent in reverse order, we're now adding - // some more childiren in normal order - - // add a new reply to the chain-starter activity - const activity8 = { - type: 'message', - timestamp: '2020-05-28T15:21:30Z', - platform: PlatformType.DISCORD, - body: 'additional reply to the reply chain', - isContribution: true, - username: 'test2', - member: member2Created.id, - score: 2, - sourceId: 'sourceId#8', - sourceParentId: 'sourceId#1', - } - - const activityCreated8 = await activityService.upsert(activity8) - - expect(activityCreated8.parentId).toBe(activityCreated1.id) - expect(activityCreated8.conversationId).toStrictEqual(conversationCreated.id) - - // add a new activity to the thread - const activity9 = { - type: 'message', - timestamp: '2020-05-28T15:35:30Z', - platform: PlatformType.DISCORD, - body: 'additional message to the thread', - isContribution: true, - username: 'test2', - member: member2Created.id, - score: 2, - sourceId: 'sourceId#9', - sourceParentId: 'sourceId#5', - } - - const activityCreated9 = await activityService.upsert(activity9) - - expect(activityCreated9.parentId).toBe(activityCreated5.id) - expect(activityCreated9.conversationId).toStrictEqual(conversationCreated2.id) - }) - - // Tests for checking channel logic when creating activity - // Settings should get updated only when a new channel is sent alog while creating activity. - it('Should create an activity with a channel which is not present in settings and add it to settings', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - await populateSegments(mockIRepositoryOptions) - const memberCreated = await new MemberService(mockIRepositoryOptions).upsert({ - username: { - [PlatformType.GITHUB]: 'test1', - }, - platform: PlatformType.GITHUB, - joinedAt: '2020-05-27T15:13:30Z', - }) - - const activity = { - type: 'activity', - timestamp: '2020-05-27T15:13:30Z', - platform: PlatformType.GITHUB, - body: 'Body', - title: 'Title', - url: 'URL', - sentiment: { - positive: 0.98, - negative: 0.0, - neutral: 0.02, - mixed: 0.0, - label: 'positive', - sentiment: 0.98, - }, - channel: 'TestChannel', - attributes: { - replies: 12, - }, - sourceId: '#sourceId', - isContribution: true, - username: 'test1', - member: memberCreated.id, - score: 1, - } - - await new ActivityService(mockIRepositoryOptions).upsert(activity) - const segmentRepository = new SegmentRepository(mockIRepositoryOptions) - const subprojectIds = (await segmentRepository.querySubprojects({})).rows.map((s) => s.id) - const activityChannels = await segmentRepository.fetchTenantActivityChannels(subprojectIds) - expect(activityChannels[activity.platform].includes(activity.channel)).toBe(true) - }) - - it('Should not create a duplicate channel when a channel is present in settings', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - await populateSegments(mockIRepositoryOptions) - const memberCreated = await new MemberService(mockIRepositoryOptions).upsert({ - username: { - [PlatformType.GITHUB]: 'test1', - }, - platform: PlatformType.GITHUB, - joinedAt: '2020-05-27T15:13:30Z', - }) - const activity = { - type: 'activity', - timestamp: '2020-05-27T15:13:30Z', - platform: PlatformType.GITHUB, - body: 'Body', - title: 'Title', - url: 'URL', - sentiment: { - positive: 0.98, - negative: 0.0, - neutral: 0.02, - mixed: 0.0, - label: 'positive', - sentiment: 0.98, - }, - channel: 'TestChannel', - attributes: { - replies: 12, - }, - sourceId: '#sourceId', - isContribution: true, - username: 'test1', - member: memberCreated.id, - score: 1, - } - - await new ActivityService(mockIRepositoryOptions).upsert(activity) - let settings = await SettingsRepository.findOrCreateDefault({}, mockIRepositoryOptions) - const activity1 = { - type: 'activity1', - timestamp: '2020-05-27T15:13:30Z', - platform: PlatformType.GITHUB, - body: 'Body', - title: 'Title', - url: 'URL', - sentiment: { - positive: 0.98, - negative: 0.0, - neutral: 0.02, - mixed: 0.0, - label: 'positive', - sentiment: 0.98, - }, - channel: 'TestChannel', - attributes: { - replies: 12, - }, - sourceId: '#sourceId', - isContribution: true, - member: memberCreated.id, - score: 1, - } - - await new ActivityService(mockIRepositoryOptions).upsert(activity) - const segmentRepository = new SegmentRepository(mockIRepositoryOptions) - const subprojectIds = (await segmentRepository.querySubprojects({})).rows.map((s) => s.id) - const activityChannels = await segmentRepository.fetchTenantActivityChannels(subprojectIds) - expect(activityChannels[activity1.platform].length).toBe(1) - }) - }) - - describe('createWithMember method', () => { - it('Create an activity with given member [no parent activity]', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - await populateSegments(mockIRepositoryOptions) - const memberAttributeSettingsService = new MemberAttributeSettingsService( - mockIRepositoryOptions, - ) - - await memberAttributeSettingsService.createPredefined(GITHUB_MEMBER_ATTRIBUTES) - await memberAttributeSettingsService.createPredefined(TWITTER_MEMBER_ATTRIBUTES) - - const member = { - username: { - [PlatformType.GITHUB]: 'anil_github', - }, - email: 'lala@l.com', - score: 10, - attributes: { - [MemberAttributeName.IS_HIREABLE]: { - [PlatformType.GITHUB]: true, - }, - [MemberAttributeName.URL]: { - [PlatformType.GITHUB]: 'https://github.com/imcvampire', - [PlatformType.TWITTER]: 'https://twitter.com/imcvampire', - }, - [MemberAttributeName.WEBSITE_URL]: { - [PlatformType.GITHUB]: 'https://imcvampire.js.org/', - }, - [MemberAttributeName.BIO]: { - [PlatformType.GITHUB]: 'Lazy geek', - }, - [MemberAttributeName.LOCATION]: { - [PlatformType.GITHUB]: 'Helsinki, Finland', - }, - }, - organisation: 'Crowd', - joinedAt: '2020-05-27T15:13:30Z', - } - - const data = { - member, - body: 'Description\nThis pull request adds a new Dashboard and related widgets. This work will probably have to be revisited as soon as possible since a lot of decisions were made, without having too much time to think about different outcomes/possibilities. We rushed these changes so that we can demo a working dashboard to YC and to our Investors.\nChanges Proposed\n\nUpdate Chart.js\nAdd two different type of widgets (number and graph)\nRemove older/default widgets from dashboard and add our own widgets\nHide some items from the menu\nAdd all widget infrastructure (actions, services, etc) to integrate with the backend\nAdd a few more CSS tweaks\n\nScreenshots', - title: 'Dashboard widgets and some other tweaks/adjustments', - url: 'https://github.com/CrowdDevHQ/crowd-web/pull/16', - sentiment: { - positive: 0.98, - negative: 0.0, - neutral: 0.02, - mixed: 0.0, - sentiment: 0.98, - label: 'positive', - }, - channel: 'https://github.com/CrowdDevHQ/crowd-web', - timestamp: '2021-09-30T14:20:27.000Z', - type: 'pull_request-closed', - isContribution: true, - platform: PlatformType.GITHUB, - score: 4, - sourceId: '#sourceId1', - } - - const activityWithMember = await new ActivityService(mockIRepositoryOptions).createWithMember( - data, - ) - - delete activityWithMember.member - delete activityWithMember.display - delete activityWithMember.objectMember - - activityWithMember.createdAt = activityWithMember.createdAt.toISOString().split('T')[0] - activityWithMember.updatedAt = activityWithMember.updatedAt.toISOString().split('T')[0] - - const memberFound = await MemberRepository.findById( - activityWithMember.memberId, - mockIRepositoryOptions, - ) - - const expectedActivityCreated = { - id: activityWithMember.id, - type: data.type, - body: data.body, - title: data.title, - url: data.url, - channel: data.channel, - sentiment: data.sentiment, - attributes: {}, - timestamp: new Date(data.timestamp), - platform: data.platform, - isContribution: data.isContribution, - score: data.score, - username: 'anil_github', - objectMemberUsername: null, - memberId: memberFound.id, - objectMemberId: null, - createdAt: SequelizeTestUtils.getNowWithoutTime(), - updatedAt: SequelizeTestUtils.getNowWithoutTime(), - tasks: [], - deletedAt: null, - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - createdById: mockIRepositoryOptions.currentUser.id, - updatedById: mockIRepositoryOptions.currentUser.id, - importHash: null, - parentId: null, - parent: null, - sourceParentId: null, - sourceId: data.sourceId, - conversationId: null, - organizationId: null, - organization: null, - } - - expect(activityWithMember).toStrictEqual(expectedActivityCreated) - }) - - it('Create an activity with given member [with parent activity, upsert member, new activity] [parent first, child later]', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - await populateSegments(mockIRepositoryOptions) - const memberAttributeSettingsService = new MemberAttributeSettingsService( - mockIRepositoryOptions, - ) - - await memberAttributeSettingsService.createPredefined(GITHUB_MEMBER_ATTRIBUTES) - await memberAttributeSettingsService.createPredefined(TWITTER_MEMBER_ATTRIBUTES) - - const member = { - username: 'anil_github', - email: 'lala@l.com', - score: 10, - attributes: { - [MemberAttributeName.IS_HIREABLE]: { - [PlatformType.GITHUB]: true, - }, - [MemberAttributeName.URL]: { - [PlatformType.GITHUB]: 'https://github.com/imcvampire', - [PlatformType.TWITTER]: 'https://twitter.com/imcvampire', - }, - [MemberAttributeName.WEBSITE_URL]: { - [PlatformType.GITHUB]: 'https://imcvampire.js.org/', - }, - [MemberAttributeName.BIO]: { - [PlatformType.GITHUB]: 'Lazy geek', - }, - [MemberAttributeName.LOCATION]: { - [PlatformType.GITHUB]: 'Helsinki, Finland', - }, - }, - organisation: 'Crowd', - joinedAt: '2020-05-27T15:13:30Z', - } - - const data = { - member, - body: 'Description\nThis pull request adds a new Dashboard and related widgets. This work will probably have to be revisited as soon as possible since a lot of decisions were made, without having too much time to think about different outcomes/possibilities. We rushed these changes so that we can demo a working dashboard to YC and to our Investors.\nChanges Proposed\n\nUpdate Chart.js\nAdd two different type of widgets (number and graph)\nRemove older/default widgets from dashboard and add our own widgets\nHide some items from the menu\nAdd all widget infrastructure (actions, services, etc) to integrate with the backend\nAdd a few more CSS tweaks\n\nScreenshots', - title: 'Dashboard widgets and some other tweaks/adjustments', - url: 'https://github.com/CrowdDevHQ/crowd-web/pull/16', - channel: 'https://github.com/CrowdDevHQ/crowd-web', - timestamp: '2021-09-30T14:20:27.000Z', - type: 'pull_request-closed', - isContribution: true, - platform: PlatformType.GITHUB, - score: 4, - sourceId: '#sourceId1', - } - - const activityWithMember1 = await new ActivityService( - mockIRepositoryOptions, - ).createWithMember(data) - - const data2 = { - member, - body: 'Description\nMinor pull request that fixes the order by Score and # of activities in the members list page', - title: 'Add order by score and # of activities', - url: 'https://github.com/CrowdDevHQ/crowd-web/pull/30', - channel: 'https://github.com/CrowdDevHQ/crowd-web', - timestamp: '2021-11-30T14:20:27.000Z', - type: 'pull_request-open', - isContribution: true, - platform: PlatformType.GITHUB, - score: 4, - sourceId: '#sourceId2', - sourceParentId: data.sourceId, - } - - const activityWithMember2 = await new ActivityService( - mockIRepositoryOptions, - ).createWithMember(data2) - - // Since an activity with a parent is created, a Conversation entity should be created at this point - // with both parent and the child activities. Try finding it using the slug (slug is generated using parent.attributes.body) - - const conversationCreated = await new ConversationService( - mockIRepositoryOptions, - ).findAndCountAll({ slug: 'description-this-pull-request-adds-a-new-dashboard-and-related' }) - - // delete models before expect because we already have ids (memberId, parentId) - delete activityWithMember2.member - delete activityWithMember2.parent - delete activityWithMember2.display - delete activityWithMember2.objectMember - - activityWithMember2.createdAt = activityWithMember2.createdAt.toISOString().split('T')[0] - activityWithMember2.updatedAt = activityWithMember2.updatedAt.toISOString().split('T')[0] - - const memberFound = await MemberRepository.findById( - activityWithMember1.memberId, - mockIRepositoryOptions, - ) - - const expectedActivityCreated = { - id: activityWithMember2.id, - body: data2.body, - title: data2.title, - url: data2.url, - channel: data2.channel, - sentiment: { - positive: 0.42, - negative: 0.42, - neutral: 0.42, - mixed: 0.42, - label: 'positive', - sentiment: 0.42, - }, - attributes: {}, - type: data2.type, - timestamp: new Date(data2.timestamp), - platform: data2.platform, - tasks: [], - isContribution: data2.isContribution, - score: data2.score, - username: 'anil_github', - objectMemberUsername: null, - memberId: memberFound.id, - objectMemberId: null, - createdAt: SequelizeTestUtils.getNowWithoutTime(), - updatedAt: SequelizeTestUtils.getNowWithoutTime(), - deletedAt: null, - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - createdById: mockIRepositoryOptions.currentUser.id, - updatedById: mockIRepositoryOptions.currentUser.id, - importHash: null, - parentId: activityWithMember1.id, - sourceParentId: data2.sourceParentId, - sourceId: data2.sourceId, - conversationId: conversationCreated.rows[0].id, - organizationId: null, - organization: null, - } - - expect(activityWithMember2).toStrictEqual(expectedActivityCreated) - }) - - it('Create an activity with given member [with parent activity, upsert member, new activity] [child first, parent later]', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - await populateSegments(mockIRepositoryOptions) - const activityService = new ActivityService(mockIRepositoryOptions) - const memberAttributeSettingsService = new MemberAttributeSettingsService( - mockIRepositoryOptions, - ) - - await memberAttributeSettingsService.createPredefined(GITHUB_MEMBER_ATTRIBUTES) - await memberAttributeSettingsService.createPredefined(TWITTER_MEMBER_ATTRIBUTES) - - const member = { - username: 'anil_github', - email: 'lala@l.com', - score: 10, - attributes: { - [MemberAttributeName.IS_HIREABLE]: { - [PlatformType.GITHUB]: true, - }, - [MemberAttributeName.URL]: { - [PlatformType.GITHUB]: 'https://github.com/imcvampire', - [PlatformType.TWITTER]: 'https://twitter.com/imcvampire', - }, - [MemberAttributeName.WEBSITE_URL]: { - [PlatformType.GITHUB]: 'https://imcvampire.js.org/', - }, - [MemberAttributeName.BIO]: { - [PlatformType.GITHUB]: 'Lazy geek', - }, - [MemberAttributeName.LOCATION]: { - [PlatformType.GITHUB]: 'Helsinki, Finland', - }, - }, - organisation: 'Crowd', - joinedAt: '2020-05-27T15:13:30Z', - } - - const dataChild = { - member, - body: 'Description\nMinor pull request that fixes the order by Score and # of activities in the members list page', - title: 'Add order by score and # of activities', - url: 'https://github.com/CrowdDevHQ/crowd-web/pull/30', - channel: 'https://github.com/CrowdDevHQ/crowd-web', - timestamp: '2021-11-30T14:20:27.000Z', - type: 'pull_request-open', - isContribution: true, - platform: PlatformType.GITHUB, - score: 4, - sourceParentId: '#sourceId1', - sourceId: '#childSourceId', - } - - let activityWithMemberChild = await activityService.createWithMember(dataChild) - - const dataParent = { - member, - body: 'Description\nThis pull request adds a new Dashboard and related widgets. This work will probably have to be revisited as soon as possible since a lot of decisions were made, without having too much time to think about different outcomes/possibilities. We rushed these changes so that we can demo a working dashboard to YC and to our Investors.\nChanges Proposed\n\nUpdate Chart.js\nAdd two different type of widgets (number and graph)\nRemove older/default widgets from dashboard and add our own widgets\nHide some items from the menu\nAdd all widget infrastructure (actions, services, etc) to integrate with the backend\nAdd a few more CSS tweaks\n\nScreenshots', - title: 'Dashboard widgets and some other tweaks/adjustments', - url: 'https://github.com/CrowdDevHQ/crowd-web/pull/16', - channel: 'https://github.com/CrowdDevHQ/crowd-web', - timestamp: '2021-09-30T14:20:27.000Z', - type: 'pull_request-closed', - isContribution: true, - platform: PlatformType.GITHUB, - score: 4, - sourceId: dataChild.sourceParentId, - } - - let activityWithMemberParent = await activityService.createWithMember(dataParent) - - // after creating parent, conversation should be started - const conversationCreated = await new ConversationService( - mockIRepositoryOptions, - ).findAndCountAll({ slug: 'description-this-pull-request-adds-a-new-dashboard-and-related' }) - - // get child and parent activity again - activityWithMemberChild = await activityService.findById(activityWithMemberChild.id) - activityWithMemberParent = await activityService.findById(activityWithMemberParent.id) - - // delete models before expect because we already have ids (memberId, parentId) - delete activityWithMemberChild.member - delete activityWithMemberChild.parent - delete activityWithMemberChild.display - delete activityWithMemberChild.objectMember - delete activityWithMemberParent.member - delete activityWithMemberParent.parent - delete activityWithMemberParent.display - delete activityWithMemberParent.objectMember - - activityWithMemberChild.createdAt = activityWithMemberChild.createdAt - .toISOString() - .split('T')[0] - activityWithMemberChild.updatedAt = activityWithMemberChild.updatedAt - .toISOString() - .split('T')[0] - activityWithMemberParent.createdAt = activityWithMemberParent.createdAt - .toISOString() - .split('T')[0] - activityWithMemberParent.updatedAt = activityWithMemberParent.updatedAt - .toISOString() - .split('T')[0] - - const memberFound = await MemberRepository.findById( - activityWithMemberChild.memberId, - mockIRepositoryOptions, - ) - - const expectedParentActivityCreated = { - id: activityWithMemberParent.id, - body: dataParent.body, - title: dataParent.title, - url: dataParent.url, - channel: dataParent.channel, - sentiment: { - positive: 0.42, - negative: 0.42, - neutral: 0.42, - mixed: 0.42, - label: 'positive', - sentiment: 0.42, - }, - attributes: {}, - type: dataParent.type, - timestamp: new Date(dataParent.timestamp), - platform: dataParent.platform, - isContribution: dataParent.isContribution, - tasks: [], - score: dataParent.score, - username: 'anil_github', - objectMemberUsername: null, - memberId: memberFound.id, - objectMemberId: null, - createdAt: SequelizeTestUtils.getNowWithoutTime(), - updatedAt: SequelizeTestUtils.getNowWithoutTime(), - deletedAt: null, - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - createdById: mockIRepositoryOptions.currentUser.id, - updatedById: mockIRepositoryOptions.currentUser.id, - importHash: null, - parentId: null, - sourceParentId: null, - sourceId: dataParent.sourceId, - conversationId: conversationCreated.rows[0].id, - organizationId: null, - organization: null, - } - - expect(activityWithMemberParent).toStrictEqual(expectedParentActivityCreated) - - const expectedChildActivityCreated = { - id: activityWithMemberChild.id, - body: dataChild.body, - title: dataChild.title, - url: dataChild.url, - channel: dataChild.channel, - sentiment: { - positive: 0.42, - negative: 0.42, - neutral: 0.42, - mixed: 0.42, - label: 'positive', - sentiment: 0.42, - }, - attributes: {}, - type: dataChild.type, - timestamp: new Date(dataChild.timestamp), - platform: dataChild.platform, - isContribution: dataChild.isContribution, - score: dataChild.score, - username: 'anil_github', - objectMemberUsername: null, - memberId: memberFound.id, - objectMemberId: null, - createdAt: SequelizeTestUtils.getNowWithoutTime(), - tasks: [], - updatedAt: SequelizeTestUtils.getNowWithoutTime(), - deletedAt: null, - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - createdById: mockIRepositoryOptions.currentUser.id, - updatedById: mockIRepositoryOptions.currentUser.id, - importHash: null, - parentId: activityWithMemberParent.id, - sourceParentId: dataChild.sourceParentId, - sourceId: dataChild.sourceId, - conversationId: conversationCreated.rows[0].id, - organizationId: null, - organization: null, - } - - expect(activityWithMemberChild).toStrictEqual(expectedChildActivityCreated) - }) - - it(`Should respect the affiliation settings when setting an activity's organization with multiple member organizations`, async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - const segmentRepo = new SegmentRepository(mockIRepositoryOptions) - - const segment1 = await segmentRepo.create({ - name: 'Crowd.dev - Segment1', - url: '', - parentName: 'Crowd.dev - Segment1', - grandparentName: 'Crowd.dev - Segment1', - slug: 'crowd.dev-1', - parentSlug: 'crowd.dev-1', - grandparentSlug: 'crowd.dev-1', - status: SegmentStatus.ACTIVE, - sourceId: null, - sourceParentId: null, - }) - - const segment2 = await segmentRepo.create({ - name: 'Crowd.dev - Segment2', - url: '', - parentName: 'Crowd.dev - Segment2', - grandparentName: 'Crowd.dev - Segment2', - slug: 'crowd.dev-2', - parentSlug: 'crowd.dev-2', - grandparentSlug: 'crowd.dev-2', - status: SegmentStatus.ACTIVE, - sourceId: null, - sourceParentId: null, - }) - - await populateSegments(mockIRepositoryOptions) - const org1 = await OrganizationRepository.create( - { - displayName: 'tesla', - }, - mockIRepositoryOptions, - ) - - const org2 = await OrganizationRepository.create( - { - displayName: 'crowd.dev', - }, - mockIRepositoryOptions, - ) - - const member = { - username: { - [PlatformType.GITHUB]: 'anil_github', - }, - organizations: [org1, org2], - affiliations: [ - { - segmentId: segment1.id, - organizationId: org2.id, - dateStart: '2021-09-01', - }, - { - segmentId: segment2.id, - organizationId: null, - dateStart: '2021-09-01', - }, - ], - } - - const data = { - member, - timestamp: '2021-09-30T14:20:27.000Z', - type: 'pull_request-closed', - platform: PlatformType.GITHUB, - sourceId: '#sourceId1', - } - - switchSegments(mockIRepositoryOptions, [segment1]) - - let activityWithMember = await new ActivityService(mockIRepositoryOptions).createWithMember( - data, - ) - - let activity = await ActivityRepository.findById( - activityWithMember.id, - mockIRepositoryOptions, - ) - - // org2 should be set as organization because it's in member's affiliated organizations - expect(activity.organization.name).toEqual(org2.name) - - // add another activity to segment2 for the same member - switchSegments(mockIRepositoryOptions, [segment2]) - - data.sourceId = '#sourceId2' - data.member = member // createWithMember modifies member, reset it - - activityWithMember = await new ActivityService(mockIRepositoryOptions).createWithMember(data) - - activity = await ActivityRepository.findById(activityWithMember.id, mockIRepositoryOptions) - - // this member had a null affiliation(meaning no organizations should be set) in segment 2 - expect(activity.organization).toBeNull() - }) - - describe('Member tests in createWithMember', () => { - it('Should set the joinedAt to the time of the activity when the member does not exist', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - await populateSegments(mockIRepositoryOptions) - const memberAttributeSettingsService = new MemberAttributeSettingsService( - mockIRepositoryOptions, - ) - - await memberAttributeSettingsService.createPredefined(GITHUB_MEMBER_ATTRIBUTES) - await memberAttributeSettingsService.createPredefined(TWITTER_MEMBER_ATTRIBUTES) - - const member = { - username: { - [PlatformType.GITHUB]: 'anil_github', - }, - email: 'lala@l.com', - score: 10, - attributes: { - [MemberAttributeName.IS_HIREABLE]: { - [PlatformType.GITHUB]: true, - }, - [MemberAttributeName.URL]: { - [PlatformType.GITHUB]: 'https://github.com/imcvampire', - [PlatformType.TWITTER]: 'https://twitter.com/imcvampire', - }, - [MemberAttributeName.WEBSITE_URL]: { - [PlatformType.GITHUB]: 'https://imcvampire.js.org/', - }, - [MemberAttributeName.BIO]: { - [PlatformType.GITHUB]: 'Lazy geek', - }, - [MemberAttributeName.LOCATION]: { - [PlatformType.GITHUB]: 'Helsinki, Finland', - }, - }, - organisation: 'Crowd', - joinedAt: '2020-05-27T15:13:30Z', - } - - const data = { - member, - body: 'Description\nThis pull request adds a new Dashboard and related widgets. This work will probably have to be revisited as soon as possible since a lot of decisions were made, without having too much time to think about different outcomes/possibilities. We rushed these changes so that we can demo a working dashboard to YC and to our Investors.\nChanges Proposed\n\nUpdate Chart.js\nAdd two different type of widgets (number and graph)\nRemove older/default widgets from dashboard and add our own widgets\nHide some items from the menu\nAdd all widget infrastructure (actions, services, etc) to integrate with the backend\nAdd a few more CSS tweaks\n\nScreenshots', - title: 'Dashboard widgets and some other tweaks/adjustments', - url: 'https://github.com/CrowdDevHQ/crowd-web/pull/16', - channel: 'https://github.com/CrowdDevHQ/crowd-web', - timestamp: '2021-09-30T14:20:27.000Z', - type: 'pull_request-closed', - isContribution: true, - platform: PlatformType.GITHUB, - score: 4, - sourceId: '#sourceId1', - } - - const activityWithMember = await new ActivityService( - mockIRepositoryOptions, - ).createWithMember(data) - - delete activityWithMember.member - delete activityWithMember.display - delete activityWithMember.objectMember - - activityWithMember.createdAt = activityWithMember.createdAt.toISOString().split('T')[0] - activityWithMember.updatedAt = activityWithMember.updatedAt.toISOString().split('T')[0] - - const memberFound = await MemberRepository.findById( - activityWithMember.memberId, - mockIRepositoryOptions, - ) - - const expectedActivityCreated = { - id: activityWithMember.id, - body: data.body, - title: data.title, - url: data.url, - channel: data.channel, - sentiment: { - positive: 0.42, - negative: 0.42, - neutral: 0.42, - mixed: 0.42, - label: 'positive', - sentiment: 0.42, - }, - attributes: {}, - type: data.type, - timestamp: new Date(data.timestamp), - platform: data.platform, - isContribution: data.isContribution, - score: data.score, - username: 'anil_github', - objectMemberUsername: null, - memberId: memberFound.id, - objectMemberId: null, - createdAt: SequelizeTestUtils.getNowWithoutTime(), - tasks: [], - updatedAt: SequelizeTestUtils.getNowWithoutTime(), - deletedAt: null, - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - createdById: mockIRepositoryOptions.currentUser.id, - updatedById: mockIRepositoryOptions.currentUser.id, - importHash: null, - parentId: null, - parent: null, - sourceParentId: null, - sourceId: data.sourceId, - conversationId: null, - organizationId: null, - organization: null, - } - - expect(activityWithMember).toStrictEqual(expectedActivityCreated) - expect(memberFound.joinedAt).toStrictEqual(expectedActivityCreated.timestamp) - expect(memberFound.username).toStrictEqual({ - [PlatformType.GITHUB]: ['anil_github'], - }) - }) - - it('Should replace joinedAt when activity ts is earlier than existing joinedAt', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - await populateSegments(mockIRepositoryOptions) - const memberAttributeSettingsService = new MemberAttributeSettingsService( - mockIRepositoryOptions, - ) - - await memberAttributeSettingsService.createPredefined(GITHUB_MEMBER_ATTRIBUTES) - await memberAttributeSettingsService.createPredefined(TWITTER_MEMBER_ATTRIBUTES) - - const member = { - username: { - [PlatformType.GITHUB]: 'anil_github', - }, - displayName: 'Anil', - email: 'lala@l.com', - score: 10, - attributes: { - [MemberAttributeName.IS_HIREABLE]: { - [PlatformType.GITHUB]: true, - }, - [MemberAttributeName.URL]: { - [PlatformType.GITHUB]: 'https://github.com/imcvampire', - [PlatformType.TWITTER]: 'https://twitter.com/imcvampire', - }, - [MemberAttributeName.WEBSITE_URL]: { - [PlatformType.GITHUB]: 'https://imcvampire.js.org/', - }, - [MemberAttributeName.BIO]: { - [PlatformType.GITHUB]: 'Lazy geek', - }, - [MemberAttributeName.LOCATION]: { - [PlatformType.GITHUB]: 'Helsinki, Finland', - }, - }, - organisation: 'Crowd', - joinedAt: '2022-05-27T15:13:30Z', - } - - await MemberRepository.create(member, mockIRepositoryOptions) - - const data = { - member, - body: 'Description\nThis pull request adds a new Dashboard and related widgets. This work will probably have to be revisited as soon as possible since a lot of decisions were made, without having too much time to think about different outcomes/possibilities. We rushed these changes so that we can demo a working dashboard to YC and to our Investors.\nChanges Proposed\n\nUpdate Chart.js\nAdd two different type of widgets (number and graph)\nRemove older/default widgets from dashboard and add our own widgets\nHide some items from the menu\nAdd all widget infrastructure (actions, services, etc) to integrate with the backend\nAdd a few more CSS tweaks\n\nScreenshots', - title: 'Dashboard widgets and some other tweaks/adjustments', - url: 'https://github.com/CrowdDevHQ/crowd-web/pull/16', - channel: 'https://github.com/CrowdDevHQ/crowd-web', - timestamp: '2021-09-30T14:20:27.000Z', - type: 'pull_request-closed', - isContribution: true, - platform: PlatformType.GITHUB, - score: 4, - sourceId: '#sourceId1', - } - - const activityWithMember = await new ActivityService( - mockIRepositoryOptions, - ).createWithMember(data) - - delete activityWithMember.member - delete activityWithMember.display - delete activityWithMember.objectMember - - activityWithMember.createdAt = activityWithMember.createdAt.toISOString().split('T')[0] - activityWithMember.updatedAt = activityWithMember.updatedAt.toISOString().split('T')[0] - - const memberFound = await MemberRepository.findById( - activityWithMember.memberId, - mockIRepositoryOptions, - ) - - const expectedActivityCreated = { - id: activityWithMember.id, - body: data.body, - title: data.title, - url: data.url, - channel: data.channel, - sentiment: { - positive: 0.42, - negative: 0.42, - neutral: 0.42, - sentiment: 0.42, - mixed: 0.42, - label: 'positive', - }, - attributes: {}, - type: data.type, - timestamp: new Date(data.timestamp), - platform: data.platform, - isContribution: data.isContribution, - score: data.score, - username: 'anil_github', - objectMemberUsername: null, - memberId: memberFound.id, - objectMemberId: null, - createdAt: SequelizeTestUtils.getNowWithoutTime(), - updatedAt: SequelizeTestUtils.getNowWithoutTime(), - deletedAt: null, - tasks: [], - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - createdById: mockIRepositoryOptions.currentUser.id, - updatedById: mockIRepositoryOptions.currentUser.id, - importHash: null, - parentId: null, - parent: null, - sourceId: data.sourceId, - sourceParentId: null, - conversationId: null, - organizationId: null, - organization: null, - } - - expect(activityWithMember).toStrictEqual(expectedActivityCreated) - expect(memberFound.joinedAt).toStrictEqual(expectedActivityCreated.timestamp) - expect(memberFound.username).toStrictEqual({ - [PlatformType.GITHUB]: ['anil_github'], - }) - }) - - it('Should not replace joinedAt when activity ts is later than existing joinedAt', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - await populateSegments(mockIRepositoryOptions) - const memberAttributeSettingsService = new MemberAttributeSettingsService( - mockIRepositoryOptions, - ) - - await memberAttributeSettingsService.createPredefined(GITHUB_MEMBER_ATTRIBUTES) - await memberAttributeSettingsService.createPredefined(TWITTER_MEMBER_ATTRIBUTES) - - const member = { - username: { - [PlatformType.GITHUB]: 'anil_github', - }, - displayName: 'Anil', - email: 'lala@l.com', - score: 10, - attributes: { - [MemberAttributeName.IS_HIREABLE]: { - [PlatformType.GITHUB]: true, - }, - [MemberAttributeName.URL]: { - [PlatformType.GITHUB]: 'https://github.com/imcvampire', - [PlatformType.TWITTER]: 'https://twitter.com/imcvampire', - }, - [MemberAttributeName.WEBSITE_URL]: { - [PlatformType.GITHUB]: 'https://imcvampire.js.org/', - }, - [MemberAttributeName.BIO]: { - [PlatformType.GITHUB]: 'Lazy geek', - }, - [MemberAttributeName.LOCATION]: { - [PlatformType.GITHUB]: 'Helsinki, Finland', - }, - }, - organisation: 'Crowd', - joinedAt: '2020-05-27T15:13:30Z', - } - - await MemberRepository.create(member, mockIRepositoryOptions) - - const data = { - member, - body: 'Description\nThis pull request adds a new Dashboard and related widgets. This work will probably have to be revisited as soon as possible since a lot of decisions were made, without having too much time to think about different outcomes/possibilities. We rushed these changes so that we can demo a working dashboard to YC and to our Investors.\nChanges Proposed\n\nUpdate Chart.js\nAdd two different type of widgets (number and graph)\nRemove older/default widgets from dashboard and add our own widgets\nHide some items from the menu\nAdd all widget infrastructure (actions, services, etc) to integrate with the backend\nAdd a few more CSS tweaks\n\nScreenshots', - title: 'Dashboard widgets and some other tweaks/adjustments', - url: 'https://github.com/CrowdDevHQ/crowd-web/pull/16', - channel: 'https://github.com/CrowdDevHQ/crowd-web', - timestamp: '2021-09-30T14:20:27.000Z', - type: 'pull_request-closed', - isContribution: true, - platform: PlatformType.GITHUB, - score: 4, - sourceId: '#sourceId1', - } - - const activityWithMember = await new ActivityService( - mockIRepositoryOptions, - ).createWithMember(data) - - delete activityWithMember.member - delete activityWithMember.display - delete activityWithMember.objectMember - - activityWithMember.createdAt = activityWithMember.createdAt.toISOString().split('T')[0] - activityWithMember.updatedAt = activityWithMember.updatedAt.toISOString().split('T')[0] - - const memberFound = await MemberRepository.findById( - activityWithMember.memberId, - mockIRepositoryOptions, - ) - - const expectedActivityCreated = { - id: activityWithMember.id, - body: data.body, - title: data.title, - url: data.url, - channel: data.channel, - sentiment: { - positive: 0.42, - negative: 0.42, - neutral: 0.42, - mixed: 0.42, - label: 'positive', - sentiment: 0.42, - }, - attributes: {}, - type: data.type, - timestamp: new Date(data.timestamp), - platform: data.platform, - isContribution: data.isContribution, - score: data.score, - username: 'anil_github', - objectMemberUsername: null, - memberId: memberFound.id, - objectMemberId: null, - createdAt: SequelizeTestUtils.getNowWithoutTime(), - updatedAt: SequelizeTestUtils.getNowWithoutTime(), - tasks: [], - deletedAt: null, - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - createdById: mockIRepositoryOptions.currentUser.id, - updatedById: mockIRepositoryOptions.currentUser.id, - importHash: null, - parentId: null, - parent: null, - sourceId: data.sourceId, - sourceParentId: null, - conversationId: null, - organizationId: null, - organization: null, - } - - expect(activityWithMember).toStrictEqual(expectedActivityCreated) - expect(memberFound.joinedAt).toStrictEqual(new Date('2020-05-27T15:13:30Z')) - expect(memberFound.username).toStrictEqual({ - [PlatformType.GITHUB]: ['anil_github'], - }) - }) - - it('It should replace joinedAt if the original was in year 1970', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - await populateSegments(mockIRepositoryOptions) - await populateSegments(mockIRepositoryOptions) - const memberAttributeSettingsService = new MemberAttributeSettingsService( - mockIRepositoryOptions, - ) - - await memberAttributeSettingsService.createPredefined(GITHUB_MEMBER_ATTRIBUTES) - await memberAttributeSettingsService.createPredefined(TWITTER_MEMBER_ATTRIBUTES) - - const member = { - username: { - [PlatformType.GITHUB]: 'anil_github', - }, - displayName: 'Anil', - email: 'lala@l.com', - score: 10, - attributes: { - [MemberAttributeName.IS_HIREABLE]: { - [PlatformType.GITHUB]: true, - }, - [MemberAttributeName.URL]: { - [PlatformType.GITHUB]: 'https://github.com/imcvampire', - [PlatformType.TWITTER]: 'https://twitter.com/imcvampire', - }, - [MemberAttributeName.WEBSITE_URL]: { - [PlatformType.GITHUB]: 'https://imcvampire.js.org/', - }, - [MemberAttributeName.BIO]: { - [PlatformType.GITHUB]: 'Computer Science', - }, - [MemberAttributeName.LOCATION]: { - [PlatformType.GITHUB]: 'Istanbul', - }, - }, - organisation: 'Crowd', - joinedAt: new Date('1970-01-01T00:00:00Z'), - } - - await MemberRepository.create(member, mockIRepositoryOptions) - - const data = { - member, - body: 'Description\nThis pull request adds a new Dashboard and related widgets. This work will probably have to be revisited as soon as possible since a lot of decisions were made, without having too much time to think about different outcomes/possibilities. We rushed these changes so that we can demo a working dashboard to YC and to our Investors.\nChanges Proposed\n\nUpdate Chart.js\nAdd two different type of widgets (number and graph)\nRemove older/default widgets from dashboard and add our own widgets\nHide some items from the menu\nAdd all widget infrastructure (actions, services, etc) to integrate with the backend\nAdd a few more CSS tweaks\n\nScreenshots', - title: 'Dashboard widgets and some other tweaks/adjustments', - state: 'merged', - url: 'https://github.com/CrowdDevHQ/crowd-web/pull/16', - channel: 'https://github.com/CrowdDevHQ/crowd-web', - timestamp: '2021-09-30T14:20:27.000Z', - type: 'pull_request-closed', - isContribution: true, - platform: PlatformType.GITHUB, - score: 4, - sourceId: '#sourceId1', - } - - const activityWithMember = await new ActivityService( - mockIRepositoryOptions, - ).createWithMember(data) - - delete activityWithMember.member - delete activityWithMember.display - delete activityWithMember.objectMember - - activityWithMember.createdAt = activityWithMember.createdAt.toISOString().split('T')[0] - activityWithMember.updatedAt = activityWithMember.updatedAt.toISOString().split('T')[0] - - const memberFound = await MemberRepository.findById( - activityWithMember.memberId, - mockIRepositoryOptions, - ) - - const expectedActivityCreated = { - id: activityWithMember.id, - body: data.body, - title: data.title, - url: data.url, - channel: data.channel, - sentiment: { - positive: 0.42, - negative: 0.42, - neutral: 0.42, - mixed: 0.42, - label: 'positive', - sentiment: 0.42, - }, - attributes: {}, - type: data.type, - timestamp: new Date(data.timestamp), - platform: data.platform, - isContribution: data.isContribution, - score: data.score, - username: 'anil_github', - objectMemberUsername: null, - memberId: memberFound.id, - objectMemberId: null, - createdAt: SequelizeTestUtils.getNowWithoutTime(), - updatedAt: SequelizeTestUtils.getNowWithoutTime(), - deletedAt: null, - tasks: [], - tenantId: mockIRepositoryOptions.currentTenant.id, - segmentId: mockIRepositoryOptions.currentSegments[0].id, - createdById: mockIRepositoryOptions.currentUser.id, - updatedById: mockIRepositoryOptions.currentUser.id, - importHash: null, - parentId: null, - parent: null, - sourceId: data.sourceId, - sourceParentId: null, - conversationId: null, - organizationId: null, - organization: null, - } - - expect(activityWithMember).toStrictEqual(expectedActivityCreated) - expect(memberFound.joinedAt).toStrictEqual(expectedActivityCreated.timestamp) - expect(memberFound.username).toStrictEqual({ - [PlatformType.GITHUB]: ['anil_github'], - }) - }) - - it('Should respect joinedAt when an existing activity comes in with a different timestamp', async () => { - // This can happen in cases like the Twitter integration. - // For follow activities, if we are onboarding we set the timestamp to 1970, - // but if we are not onboarding, we set the timestamp to the current time. - // This can cause having 2 activities with different timestamps, but the same sourceId. - // The joinedAt should stay untouched in this case. - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - await populateSegments(mockIRepositoryOptions) - const memberAttributeSettingsService = new MemberAttributeSettingsService( - mockIRepositoryOptions, - ) - - await memberAttributeSettingsService.createPredefined(GITHUB_MEMBER_ATTRIBUTES) - await memberAttributeSettingsService.createPredefined(TWITTER_MEMBER_ATTRIBUTES) - - const data = { - member: { - username: 'anil', - }, - timestamp: '1970-01-01T00:00:00.000Z', - type: 'follow', - platform: PlatformType.TWITTER, - sourceId: '#sourceId1', - } - - const activityWithMember = await new ActivityService( - mockIRepositoryOptions, - ).createWithMember(data) - - const data2 = { - member: { - username: 'anil', - }, - timestamp: '2021-09-30T14:20:27.000Z', - type: 'follow', - platform: PlatformType.TWITTER, - sourceId: '#sourceId1', - } - // Upsert the same activity with a different timestamp - await new ActivityService(mockIRepositoryOptions).createWithMember(data2) - - const memberFound = await MemberRepository.findById( - activityWithMember.memberId, - mockIRepositoryOptions, - ) - // The joinedAt should stay untouched - expect(memberFound.joinedAt).toStrictEqual(new Date('1970-01-01T00:00:00.000Z')) - }) - }) - }) - - describe('addToConversation method', () => { - it('Should create a new conversation and add the activities in, when parent and child has no conversation', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - const activityService = new ActivityService(mockIRepositoryOptions) - - const memberCreated = await new MemberService(mockIRepositoryOptions).upsert({ - username: { - [PlatformType.GITHUB]: 'test', - }, - platform: PlatformType.GITHUB, - joinedAt: '2020-05-27T15:13:30Z', - }) - - const activityParent = { - type: 'activity', - timestamp: '2020-05-27T14:13:30Z', - platform: PlatformType.GITHUB, - channel: 'https://github.com/CrowdDevHQ/crowd-web', - isContribution: true, - username: 'test', - member: memberCreated.id, - score: 1, - sourceId: '#sourceId1', - } - - let activityParentCreated = await ActivityRepository.create( - activityParent, - mockIRepositoryOptions, - ) - - const activityChild = { - type: 'activity', - timestamp: '2020-05-27T15:13:30Z', - platform: PlatformType.GITHUB, - channel: 'https://github.com/CrowdDevHQ/crowd-web', - isContribution: true, - username: 'test', - member: memberCreated.id, - score: 1, - parent: activityParentCreated.id, - sourceId: '#sourceId2', - } - - let activityChildCreated = await ActivityRepository.create( - activityChild, - mockIRepositoryOptions, - ) - - const transaction = await SequelizeRepository.createTransaction(mockIRepositoryOptions) - - await activityService.addToConversation( - activityChildCreated.id, - activityParentCreated.id, - transaction, - ) - - await SequelizeRepository.commitTransaction(transaction) - - const conversationCreated = ( - await new ConversationService(mockIRepositoryOptions).findAndCountAll({ - slug: 'some-parent-activity', - }) - ).rows[0] - - // get activities again - activityChildCreated = await activityService.findById(activityChildCreated.id) - activityParentCreated = await activityService.findById(activityParentCreated.id) - - // activities should belong to the newly created conversation - expect(activityChildCreated.conversationId).toBe(conversationCreated.id) - expect(activityParentCreated.conversationId).toBe(conversationCreated.id) - }) - - it('Should add the child activity to parents conversation, when parent already has a conversation', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - const activityService = new ActivityService(mockIRepositoryOptions) - const conversationService = new ConversationService(mockIRepositoryOptions) - - const memberCreated = await new MemberService(mockIRepositoryOptions).upsert({ - username: { - [PlatformType.GITHUB]: 'test', - }, - platform: PlatformType.GITHUB, - joinedAt: '2020-05-27T15:13:30Z', - }) - - const conversation = await conversationService.create({ - slug: 'some-slug', - title: 'some title', - }) - - const activityParent = { - type: 'activity', - timestamp: '2020-05-27T14:13:30Z', - platform: PlatformType.GITHUB, - channel: 'https://github.com/CrowdDevHQ/crowd-web', - isContribution: true, - username: 'test', - member: memberCreated.id, - score: 1, - conversationId: conversation.id, - sourceId: '#sourceId1', - } - - const activityParentCreated = await ActivityRepository.create( - activityParent, - mockIRepositoryOptions, - ) - - const activityChild = { - type: 'activity', - timestamp: '2020-05-27T15:13:30Z', - platform: PlatformType.GITHUB, - channel: 'https://github.com/CrowdDevHQ/crowd-web', - isContribution: true, - username: 'test', - member: memberCreated.id, - score: 1, - parent: activityParentCreated.id, - sourceId: '#sourceId2', - } - - let activityChildCreated = await ActivityRepository.create( - activityChild, - mockIRepositoryOptions, - ) - - const transaction = await SequelizeRepository.createTransaction(mockIRepositoryOptions) - - await activityService.addToConversation( - activityChildCreated.id, - activityParentCreated.id, - transaction, - ) - - await SequelizeRepository.commitTransaction(transaction) - - // get child activity again - activityChildCreated = await activityService.findById(activityChildCreated.id) - - // child should be added to already existing conservation - expect(activityChildCreated.conversationId).toBe(conversation.id) - expect(activityParentCreated.conversationId).toBe(conversation.id) - }) - - it('Should add the parent activity to childs conversation and update conversation [published=false] title&slug, when child already has a conversation', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - const activityService = new ActivityService(mockIRepositoryOptions) - const conversationService = new ConversationService(mockIRepositoryOptions) - - const memberCreated = await new MemberService(mockIRepositoryOptions).upsert({ - username: { - [PlatformType.GITHUB]: 'test', - }, - platform: PlatformType.GITHUB, - joinedAt: '2020-05-27T15:13:30Z', - }) - - let conversation = await conversationService.create({ - slug: 'some-slug', - title: 'some title', - }) - - const activityParent = { - type: 'activity', - timestamp: '2020-05-27T14:13:30Z', - platform: PlatformType.GITHUB, - channel: 'https://github.com/CrowdDevHQ/crowd-web', - body: 'Some Parent Activity', - isContribution: true, - username: 'test', - member: memberCreated.id, - score: 1, - sourceId: '#sourceId1', - } - - let activityParentCreated = await ActivityRepository.create( - activityParent, - mockIRepositoryOptions, - ) - - const activityChild = { - type: 'activity', - timestamp: '2020-05-27T15:13:30Z', - platform: PlatformType.GITHUB, - isContribution: true, - username: 'test', - member: memberCreated.id, - score: 1, - parent: activityParentCreated.id, - conversationId: conversation.id, - sourceId: '#sourceId2', - } - - const activityChildCreated = await ActivityRepository.create( - activityChild, - mockIRepositoryOptions, - ) - - const transaction = await SequelizeRepository.createTransaction(mockIRepositoryOptions) - - await activityService.addToConversation( - activityChildCreated.id, - activityParentCreated.id, - transaction, - ) - - await SequelizeRepository.commitTransaction(transaction) - - // get the conversation again - conversation = await conversationService.findById(conversation.id) - - // conversation should be updated with newly added parents body - expect(conversation.title).toBe('Some Parent Activity') - expect(conversation.slug).toBe('some-parent-activity') - - // get parent activity again - activityParentCreated = await activityService.findById(activityParentCreated.id) - - // parent should be added to the conversation - expect(activityChildCreated.conversationId).toBe(conversation.id) - expect(activityParentCreated.conversationId).toBe(conversation.id) - }) - - it('Should add the parent activity to childs conversation and NOT update conversation [published=true] title&slug, when child already has a conversation', async () => { - let mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const activityService = new ActivityService(mockIRepositoryOptions) - const conversationService = new ConversationService(mockIRepositoryOptions) - - const memberCreated = await new MemberService(mockIRepositoryOptions).upsert({ - username: { - [PlatformType.GITHUB]: 'test', - }, - platform: PlatformType.GITHUB, - joinedAt: '2020-05-27T15:13:30Z', - }) - - let conversation = await conversationService.create({ - slug: 'some-slug', - title: 'some title', - published: true, - }) - - const activityParent = { - type: 'activity', - timestamp: '2020-05-27T14:13:30Z', - platform: PlatformType.GITHUB, - body: 'Some Parent Activity', - channel: 'https://github.com/CrowdDevHQ/crowd-web', - isContribution: true, - username: 'test', - member: memberCreated.id, - score: 1, - sourceId: '#sourceId1', - } - - let activityParentCreated = await ActivityRepository.create( - activityParent, - mockIRepositoryOptions, - ) - - const activityChild = { - type: 'activity', - timestamp: '2020-05-27T15:13:30Z', - platform: PlatformType.GITHUB, - body: 'Here', - channel: 'https://github.com/CrowdDevHQ/crowd-web', - isContribution: true, - username: 'test', - member: memberCreated.id, - score: 1, - parent: activityParentCreated.id, - conversationId: conversation.id, - sourceId: '#sourceId2', - } - - const activityChildCreated = await ActivityRepository.create( - activityChild, - mockIRepositoryOptions, - ) - - const transaction = await SequelizeRepository.createTransaction(mockIRepositoryOptions) - - await activityService.addToConversation( - activityChildCreated.id, - activityParentCreated.id, - transaction, - ) - - await SequelizeRepository.commitTransaction(transaction) - - // get the conversation again - conversation = await conversationService.findById(conversation.id) - - // conversation fields should NOT be updated because it's already published - expect(conversation.title).toBe('some title') - expect(conversation.slug).toBe('some-slug') - - // get parent activity again - activityParentCreated = await activityService.findById(activityParentCreated.id) - - // parent should be added to the conversation - expect(activityChildCreated.conversationId).toBe(conversation.id) - expect(activityParentCreated.conversationId).toBe(conversation.id) - }) - - it('Should always auto-publish when conversationSettings.autoPublish.status is set to all', async () => { - let mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const activityService = new ActivityService(mockIRepositoryOptions) - await SettingsRepository.findOrCreateDefault( - { website: 'https://some-website' }, - mockIRepositoryOptions, - ) - await ConversationSettingsRepository.findOrCreateDefault( - { - autoPublish: { - status: 'all', - }, - }, - mockIRepositoryOptions, - ) - - const memberCreated = await new MemberService(mockIRepositoryOptions).upsert({ - username: { - [PlatformType.GITHUB]: 'test', - }, - platform: PlatformType.GITHUB, - joinedAt: '2020-05-27T15:13:30Z', - }) - - const activityParent = { - type: 'activity', - timestamp: '2020-05-27T14:13:30Z', - platform: PlatformType.GITHUB, - body: 'Some Parent Activity', - channel: 'https://github.com/CrowdDevHQ/crowd-web', - isContribution: true, - username: 'test', - member: memberCreated.id, - score: 1, - sourceId: '#sourceId1', - } - - let activityParentCreated = await ActivityRepository.create( - activityParent, - mockIRepositoryOptions, - ) - - const activityChild = { - type: 'activity', - timestamp: '2020-05-27T15:13:30Z', - platform: PlatformType.GITHUB, - body: 'Here', - channel: 'https://github.com/CrowdDevHQ/crowd-web', - isContribution: true, - username: 'test', - member: memberCreated.id, - score: 1, - parent: activityParentCreated.id, - sourceId: '#sourceId2', - } - - let activityChildCreated = await ActivityRepository.create( - activityChild, - mockIRepositoryOptions, - ) - - const transaction = await SequelizeRepository.createTransaction(mockIRepositoryOptions) - - await activityService.addToConversation( - activityChildCreated.id, - activityParentCreated.id, - transaction, - ) - - const conversationCreated = ( - await new ConversationService({ - ...mockIRepositoryOptions, - transaction, - } as IServiceOptions).findAndCountAll({ - slug: 'some-parent-activity', - }) - ).rows[0] - - await SequelizeRepository.commitTransaction(transaction) - - // get activities again - activityChildCreated = await activityService.findById(activityChildCreated.id) - activityParentCreated = await activityService.findById(activityParentCreated.id) - - // activities should belong to the newly created conversation - expect(activityChildCreated.conversationId).toBe(conversationCreated.id) - expect(activityParentCreated.conversationId).toBe(conversationCreated.id) - - expect(conversationCreated.published).toStrictEqual(true) - }) - - it('Should never auto-publish when conversationSettings.autoPublish.status is set to disabled', async () => { - let mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const activityService = new ActivityService(mockIRepositoryOptions) - await SettingsRepository.findOrCreateDefault( - { website: 'https://some-website' }, - mockIRepositoryOptions, - ) - await ConversationSettingsRepository.findOrCreateDefault( - { - autoPublish: { - status: 'disabled', - }, - }, - mockIRepositoryOptions, - ) - - const memberCreated = await new MemberService(mockIRepositoryOptions).upsert({ - username: { - [PlatformType.GITHUB]: 'test', - }, - platform: PlatformType.GITHUB, - joinedAt: '2020-05-27T15:13:30Z', - }) - - const activityParent = { - type: 'activity', - timestamp: '2020-05-27T14:13:30Z', - platform: PlatformType.GITHUB, - body: 'Some Parent Activity', - channel: 'https://github.com/CrowdDevHQ/crowd-web', - isContribution: true, - username: 'test', - member: memberCreated.id, - score: 1, - sourceId: '#sourceId1', - } - - let activityParentCreated = await ActivityRepository.create( - activityParent, - mockIRepositoryOptions, - ) - - const activityChild = { - type: 'activity', - timestamp: '2020-05-27T15:13:30Z', - platform: PlatformType.GITHUB, - body: 'Here', - channel: 'https://github.com/CrowdDevHQ/crowd-web', - isContribution: true, - username: 'test', - member: memberCreated.id, - score: 1, - parent: activityParentCreated.id, - sourceId: '#sourceId2', - } - - let activityChildCreated = await ActivityRepository.create( - activityChild, - mockIRepositoryOptions, - ) - - const transaction = await SequelizeRepository.createTransaction(mockIRepositoryOptions) - - await activityService.addToConversation( - activityChildCreated.id, - activityParentCreated.id, - transaction, - ) - - const conversationCreated = ( - await new ConversationService({ - ...mockIRepositoryOptions, - transaction, - } as IServiceOptions).findAndCountAll({ - slug: 'some-parent-activity', - }) - ).rows[0] - - await SequelizeRepository.commitTransaction(transaction) - - // get activities again - activityChildCreated = await activityService.findById(activityChildCreated.id) - activityParentCreated = await activityService.findById(activityParentCreated.id) - - // activities should belong to the newly created conversation - expect(activityChildCreated.conversationId).toBe(conversationCreated.id) - expect(activityParentCreated.conversationId).toBe(conversationCreated.id) - - expect(conversationCreated.published).toStrictEqual(false) - }) - - it('Should auto-publish when conversationSettings.autoPublish.status is set to custom and rules match', async () => { - let mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const activityService = new ActivityService(mockIRepositoryOptions) - await SettingsRepository.findOrCreateDefault( - { website: 'https://some-website' }, - mockIRepositoryOptions, - ) - await ConversationSettingsRepository.findOrCreateDefault( - { - autoPublish: { - status: 'custom', - channelsByPlatform: { - [PlatformType.GITHUB]: ['crowd-web'], - }, - }, - }, - mockIRepositoryOptions, - ) - - const memberCreated = await new MemberService(mockIRepositoryOptions).upsert({ - username: { - [PlatformType.GITHUB]: 'test', - }, - platform: PlatformType.GITHUB, - joinedAt: '2020-05-27T15:13:30Z', - }) - - const activityParent = { - type: 'activity', - timestamp: '2020-05-27T14:13:30Z', - platform: PlatformType.GITHUB, - body: 'Some Parent Activity', - channel: 'https://github.com/CrowdDevHQ/crowd-web', - isContribution: true, - username: 'test', - member: memberCreated.id, - score: 1, - sourceId: '#sourceId1', - } - - let activityParentCreated = await ActivityRepository.create( - activityParent, - mockIRepositoryOptions, - ) - - const activityChild = { - type: 'activity', - timestamp: '2020-05-27T15:13:30Z', - platform: PlatformType.GITHUB, - body: 'Here', - channel: 'https://github.com/CrowdDevHQ/crowd-web', - isContribution: true, - username: 'test', - member: memberCreated.id, - score: 1, - parent: activityParentCreated.id, - sourceId: '#sourceId2', - } - - let activityChildCreated = await ActivityRepository.create( - activityChild, - mockIRepositoryOptions, - ) - - const transaction = await SequelizeRepository.createTransaction(mockIRepositoryOptions) - - await activityService.addToConversation( - activityChildCreated.id, - activityParentCreated.id, - transaction, - ) - - const conversationCreated = ( - await new ConversationService({ - ...mockIRepositoryOptions, - transaction, - } as IServiceOptions).findAndCountAll({ - slug: 'some-parent-activity', - }) - ).rows[0] - - await SequelizeRepository.commitTransaction(transaction) - - // get activities again - activityChildCreated = await activityService.findById(activityChildCreated.id) - activityParentCreated = await activityService.findById(activityParentCreated.id) - - // activities should belong to the newly created conversation - expect(activityChildCreated.conversationId).toBe(conversationCreated.id) - expect(activityParentCreated.conversationId).toBe(conversationCreated.id) - - expect(conversationCreated.published).toStrictEqual(true) - }) - - it("Should not auto-publish when conversationSettings.autoPublish.status is set to custom and rules don't match", async () => { - let mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - - const activityService = new ActivityService(mockIRepositoryOptions) - await SettingsRepository.findOrCreateDefault( - { website: 'https://some-website' }, - mockIRepositoryOptions, - ) - await ConversationSettingsRepository.findOrCreateDefault( - { - autoPublish: { - status: 'custom', - channelsByPlatform: { - [PlatformType.GITHUB]: ['a-different-test-channel'], - }, - }, - }, - mockIRepositoryOptions, - ) - - const memberCreated = await new MemberService(mockIRepositoryOptions).upsert({ - username: { - [PlatformType.GITHUB]: 'test', - }, - platform: PlatformType.GITHUB, - joinedAt: '2020-05-27T15:13:30Z', - }) - - const activityParent = { - type: 'activity', - timestamp: '2020-05-27T14:13:30Z', - platform: PlatformType.GITHUB, - body: 'Some Parent Activity', - channel: 'https://github.com/CrowdDevHQ/crowd-web', - isContribution: true, - username: 'test', - member: memberCreated.id, - score: 1, - sourceId: '#sourceId1', - } - - let activityParentCreated = await ActivityRepository.create( - activityParent, - mockIRepositoryOptions, - ) - - const activityChild = { - type: 'activity', - timestamp: '2020-05-27T15:13:30Z', - platform: PlatformType.GITHUB, - body: 'Here', - isContribution: true, - username: 'test', - member: memberCreated.id, - score: 1, - parent: activityParentCreated.id, - sourceId: '#sourceId2', - } - - let activityChildCreated = await ActivityRepository.create( - activityChild, - mockIRepositoryOptions, - ) - - const transaction = await SequelizeRepository.createTransaction(mockIRepositoryOptions) - - await activityService.addToConversation( - activityChildCreated.id, - activityParentCreated.id, - transaction, - ) - - const conversations = await new ConversationService({ - ...mockIRepositoryOptions, - transaction, - } as IServiceOptions).findAndCountAll({ - slug: 'some-parent-activity', - }) - - const conversationCreated = conversations.rows[0] - - await SequelizeRepository.commitTransaction(transaction) - - // get activities again - activityChildCreated = await activityService.findById(activityChildCreated.id) - activityParentCreated = await activityService.findById(activityParentCreated.id) - - // activities should belong to the newly created conversation - expect(activityChildCreated.conversationId).toBe(conversationCreated.id) - expect(activityParentCreated.conversationId).toBe(conversationCreated.id) - - expect(conversationCreated.published).toStrictEqual(false) - }) - }) - - describe('affiliations', () => { - let options - let activityService: ActivityService - let memberService - let organizationService - let segmentService: SegmentService - let memberAffiliationService: MemberAffiliationService - let memberSegmentAffiliationRepository: MemberSegmentAffiliationRepository - - let defaultActivity - let defaultMember - - beforeEach(async () => { - options = await SequelizeTestUtils.getTestIRepositoryOptions(db) - await populateSegments(options) - - activityService = new ActivityService(options) - memberService = new MemberService(options) - organizationService = new OrganizationService(options) - segmentService = new SegmentService(options) - memberAffiliationService = new MemberAffiliationService(options) - memberSegmentAffiliationRepository = new MemberSegmentAffiliationRepository(options) - - defaultActivity = { - type: 'question', - timestamp: '2020-05-27T15:13:30Z', - username: 'test', - platform: PlatformType.GITHUB, - } - defaultMember = { - platform: PlatformType.GITHUB, - joinedAt: '2020-05-27T15:13:30Z', - } - }) - - async function createMember(data = {}) { - return await memberService.upsert({ - ...defaultMember, - username: { - [PlatformType.GITHUB]: uuid(), - }, - ...data, - }) - } - - async function createActivity(memberId, data: any = {}) { - const activity = await activityService.upsert({ - ...defaultActivity, - sourceId: uuid(), - member: memberId, - ...data, - }) - - if (data.organizationId) { - await ActivityRepository.update( - activity.id, - { - organizationId: data.organizationId, - }, - options, - ) - return await activityService.findById(activity.id) - } - - return activity - } - - async function findActivity(id) { - return await activityService.findById(id) - } - - async function createOrg(name, data = {}) { - return await organizationService.createOrUpdate({ - identities: [ - { - name, - platform: 'crowd', - }, - ], - ...data, - }) - } - - async function createSegment(slug, data = {}) { - const db1 = await SequelizeTestUtils.getDatabase(db) - const tenant = options.currentTenant - try { - const segment = ( - await db1.segment.create({ - url: tenant.url, - name: slug, - parentName: tenant.name, - grandparentName: tenant.name, - slug: slug, - parentSlug: 'default', - grandparentSlug: 'default', - status: SegmentStatus.ACTIVE, - description: null, - sourceId: null, - sourceParentId: null, - tenantId: tenant.id, - }) - ).get({ plain: true }) - return segment - } catch (error) { - console.log(error) - throw error - } - } - - async function addWorkExperience(memberId, orgId, data = {}) { - return await MemberRepository.createOrUpdateWorkExperience( - { - memberId, - organizationId: orgId, - updateAffiliation: false, - source: 'test', - ...data, - }, - options, - ) - } - - describe('new activities', () => { - it('Should affiliate nothing if member has no organizations and no affiliations', async () => { - const member = await createMember() - const activity = await createActivity(member.id) - - expect(activity.organization).toBeNull() - }) - - it('Should affiliate work experience if member has organizations', async () => { - const member = await createMember() - const organization = await createOrg('hello') - await addWorkExperience(member.id, organization.id, { - dateStart: '2020-01-01', - }) - const activity = await createActivity(member.id, { - timestamp: '2023-01-01', - }) - - expect(activity.organization.id).toBe(organization.id) - }) - - it('Should affiliate with matching work experience if activity is from the past', async () => { - const member = await createMember() - const org1 = await createOrg('org1') - const org2 = await createOrg('org2') - - await addWorkExperience(member.id, org1.id, { - dateStart: '2020-01-01', - dateEnd: '2020-02-01', - }) - await addWorkExperience(member.id, org2.id, { - dateStart: '2020-02-01', - }) - - const activity = await createActivity(member.id, { - timestamp: '2020-01-15', - }) - - expect(activity.organization.id).toBe(org1.id) - }) - - it('Should affiliate with most recent open work experience if member has multiple organizations', async () => { - const member = await createMember() - const org1 = await createOrg('org1') - const org2 = await createOrg('org2') - - await addWorkExperience(member.id, org1.id, { - dateStart: '2020-01-01', - }) - await addWorkExperience(member.id, org2.id, { - dateStart: '2020-02-01', - }) - - const activity = await createActivity(member.id, { - timestamp: '2020-03-01', - }) - - expect(activity.organization.id).toBe(org2.id) - }) - - it('Should affiliate with most recent open work experience, even if there is a more recent closed one', async () => { - const member = await createMember() - const org1 = await createOrg('org1') - const org2 = await createOrg('org2') - - await addWorkExperience(member.id, org1.id, { - dateStart: '2020-01-01', - }) - await addWorkExperience(member.id, org2.id, { - dateStart: '2020-02-01', - dateEnd: '2020-03-01', - }) - - const activity = await createActivity(member.id) - - expect(activity.organization.id).toBe(org1.id) - }) - - it('Should affiliate with manual affiliation if member has organizations and affiliations', async () => { - const member = await createMember() - const org1 = await createOrg('org1') - const org2 = await createOrg('org2') - - await addWorkExperience(member.id, org1.id, { - dateStart: '2020-01-01', - }) - - await memberSegmentAffiliationRepository.createOrUpdate({ - memberId: member.id, - segmentId: options.currentSegments[0].id, - organizationId: org2.id, - dateStart: '2020-02-01', - }) - - const activity = await createActivity(member.id) - - expect(activity.organization.id).toBe(org2.id) - }) - - it('Should affiliate to invidiual if member has organizations and affiliations', async () => { - const member = await createMember() - const org1 = await createOrg('org1') - - await addWorkExperience(member.id, org1.id, { - dateStart: '2020-01-01', - }) - - await memberSegmentAffiliationRepository.createOrUpdate({ - memberId: member.id, - segmentId: options.currentSegments[0].id, - organizationId: null, - dateStart: '2020-02-01', - }) - - const activity = await createActivity(member.id) - - expect(activity.organization).toBeNull() - }) - - it('Should not affiliate if there are no relevant manual affiliations', async () => { - const member = await createMember() - const org1 = await createOrg('org1') - const segment1 = await createSegment('segment1') - - await memberSegmentAffiliationRepository.createOrUpdate({ - memberId: member.id, - segmentId: segment1.id, - organizationId: org1.id, - }) - - const activity = await createActivity(member.id) - - expect(activity.organization).toBeNull() - }) - }) - - describe('existing activities', () => { - it('Should clear affiliation if there is a manual individual affiliation', async () => { - const member = await createMember() - const org1 = await createOrg('org1') - const segment1 = await createSegment('segment1') - - await memberSegmentAffiliationRepository.createOrUpdate({ - memberId: member.id, - segmentId: segment1.id, - organizationId: null, - }) - - let activity = await createActivity(member.id, { - organizationId: org1.id, - }) - - await memberAffiliationService.updateAffiliation(member.id) - - activity = await findActivity(activity.id) - - expect(activity.organization).toBeNull() - }) - - it('Should affiliate activities', async () => { - const member = await createMember() - - let activity1 = await createActivity(member.id) - let activity2 = await createActivity(member.id) - - const org = await createOrg('org') - await addWorkExperience(member.id, org.id, { - dateStart: '2020-01-01', - }) - - await memberAffiliationService.updateAffiliation(member.id) - - activity1 = await findActivity(activity1.id) - activity2 = await findActivity(activity2.id) - - expect(activity1.organization.id).toBe(org.id) - expect(activity2.organization.id).toBe(org.id) - }) - - it('Should only affiliate activities of specific member', async () => { - const member1 = await createMember() - const member2 = await createMember() - - let activity1 = await createActivity(member1.id) - let activity2 = await createActivity(member2.id) - - const org1 = await createOrg('org1') - await addWorkExperience(member1.id, org1.id, { - dateStart: '2020-01-01', - }) - const org2 = await createOrg('org2') - await addWorkExperience(member2.id, org2.id, { - dateStart: '2020-01-01', - }) - - await memberAffiliationService.updateAffiliation(member1.id) - - activity2 = await findActivity(activity2.id) - - expect(activity2.organization).toBeNull() - }) - - it('Should affiliate with matching recent work experience', async () => { - const member = await createMember() - - let activity = await createActivity(member.id, { - timestamp: '2020-01-01', - }) - - const org1 = await createOrg('org1') - await addWorkExperience(member.id, org1.id) - const org2 = await createOrg('org2') - await addWorkExperience(member.id, org2.id, { - dateStart: '2023-01-01', - }) - const org3 = await createOrg('org2') - await addWorkExperience(member.id, org3.id, { - dateStart: '2019-01-01', - dateEnd: '2022-01-01', - }) - - await memberAffiliationService.updateAffiliation(member.id) - - activity = await findActivity(activity.id) - - expect(activity.organization.id).toBe(org3.id) - }) - - it('Should affiliate first created org to past activities', async () => { - const member = await createMember() - - let activity = await createActivity(member.id, { - timestamp: '2022-05-01', - }) - - const org1 = await createOrg('org1') - await addWorkExperience(member.id, org1.id) - const org2 = await createOrg('org2') - await addWorkExperience(member.id, org2.id, { - dateStart: '2023-01-01', - }) - const org3 = await createOrg('org2') - await addWorkExperience(member.id, org3.id, { - dateStart: '2019-01-01', - dateEnd: '2022-01-01', - }) - - await memberAffiliationService.updateAffiliation(member.id) - - activity = await findActivity(activity.id) - - expect(activity.organization.id).toBe(org1.id) - }) - - it('Should prefer manual affiliation over work experience', async () => { - const member = await createMember() - - let activity = await createActivity(member.id, { - timestamp: '2020-05-01', - }) - - const org1 = await createOrg('org1') - await addWorkExperience(member.id, org1.id, { - dateStart: '2020-01-01', - }) - - const org2 = await createOrg('org2') - await memberSegmentAffiliationRepository.createOrUpdate({ - memberId: member.id, - segmentId: options.currentSegments[0].id, - organizationId: org2.id, - dateStart: '2020-01-01', - }) - - await memberAffiliationService.updateAffiliation(member.id) - - activity = await findActivity(activity.id) - - expect(activity.organization.id).toBe(org2.id) - }) - - it('Should prefer manual individual affiliation over work experience', async () => { - const member = await createMember() - - let activity = await createActivity(member.id, { - timestamp: '2020-05-01', - }) - - const org1 = await createOrg('org1') - await addWorkExperience(member.id, org1.id, { - dateStart: '2020-01-01', - }) - - await memberSegmentAffiliationRepository.createOrUpdate({ - memberId: member.id, - segmentId: options.currentSegments[0].id, - organizationId: null, - dateStart: '2020-01-01', - }) - - await memberAffiliationService.updateAffiliation(member.id) - - activity = await findActivity(activity.id) - - expect(activity.organization).toBeNull() - }) - - it('Should trigger affiliation update when changing member organizations', async () => { - const member = await createMember() - - let activity = await createActivity(member.id, { - timestamp: '2020-05-01', - }) - - const org1 = await createOrg('org1') - await addWorkExperience(member.id, org1.id, { - dateStart: '2020-01-01', - updateAffiliation: true, - }) - - activity = await findActivity(activity.id) - - expect(activity.organization.id).toBe(org1.id) - }) - - it('Should trigger affiliation update when changing member manual affiliations', async () => { - const member = await createMember() - - let activity = await createActivity(member.id) - - const org1 = await createOrg('org1') - - await memberSegmentAffiliationRepository.createOrUpdate({ - memberId: member.id, - segmentId: options.currentSegments[0].id, - organizationId: org1.id, - }) - - activity = await findActivity(activity.id) - - expect(activity.organization.id).toBe(org1.id) - }) - }) - - it('Should filter by organization based on organizationId', async () => { - const member = await createMember() - - const org1 = await createOrg('org1') - await addWorkExperience(member.id, org1.id) - - const org2 = await createOrg('org2') - await addWorkExperience(member.id, org2.id) - - let activity1 = await createActivity(member.id, { - organizationId: org1.id, - }) - let activity2 = await createActivity(member.id, { - organizationId: org2.id, - }) - - const { rows } = await activityService.query({ - filter: { - organizations: [org1.id], - }, - }) - - expect(rows.length).toBe(1) - }) - }) -}) diff --git a/backend/src/services/__tests__/memberService.test.ts b/backend/src/services/__tests__/memberService.test.ts deleted file mode 100644 index e17404e46d..0000000000 --- a/backend/src/services/__tests__/memberService.test.ts +++ /dev/null @@ -1,3191 +0,0 @@ -import { generateUUIDv1, Error400, Error404 } from '@crowd/common' -import SequelizeTestUtils from '../../database/utils/sequelizeTestUtils' -import MemberService from '../memberService' -import MemberRepository from '../../database/repositories/memberRepository' -import ActivityRepository from '../../database/repositories/activityRepository' -import TagRepository from '../../database/repositories/tagRepository' -import { MemberAttributeName, MemberAttributeType, PlatformType } from '@crowd/types' -import OrganizationRepository from '../../database/repositories/organizationRepository' -import TaskRepository from '../../database/repositories/taskRepository' -import NoteRepository from '../../database/repositories/noteRepository' -import MemberAttributeSettingsService from '../memberAttributeSettingsService' -import SettingsRepository from '../../database/repositories/settingsRepository' -import OrganizationService from '../organizationService' -import Plans from '../../security/plans' -import lodash from 'lodash' -import { - DEVTO_MEMBER_ATTRIBUTES, - DISCORD_MEMBER_ATTRIBUTES, - GITHUB_MEMBER_ATTRIBUTES, - SLACK_MEMBER_ATTRIBUTES, - TWITTER_MEMBER_ATTRIBUTES, -} from '@crowd/integrations' - -const db = null - -describe('MemberService tests', () => { - beforeEach(async () => { - await SequelizeTestUtils.wipeDatabase(db) - }) - - afterAll(async () => { - // Closing the DB connection allows Jest to exit successfully. - await SequelizeTestUtils.closeConnection(db) - }) - - describe('upsert method', () => { - it('Should throw 400 error when platform does not exist in member data', async () => { - const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db) - - const mas = new MemberAttributeSettingsService(mockIServiceOptions) - - await mas.createPredefined(GITHUB_MEMBER_ATTRIBUTES) - - const member1 = { - username: { - [PlatformType.GITHUB]: { - username: 'anil', - integrationId: generateUUIDv1(), - }, - }, - emails: ['lala@l.com'], - score: 10, - attributes: { - [MemberAttributeName.IS_HIREABLE]: { - [PlatformType.GITHUB]: true, - }, - [MemberAttributeName.URL]: { - [PlatformType.GITHUB]: 'https://github.com/imcvampire', - }, - [MemberAttributeName.WEBSITE_URL]: { - [PlatformType.GITHUB]: 'https://imcvampire.js.org/', - }, - [MemberAttributeName.BIO]: { - [PlatformType.GITHUB]: 'Lazy geek', - }, - [MemberAttributeName.LOCATION]: { - [PlatformType.GITHUB]: 'Helsinki, Finland', - }, - }, - joinedAt: '2020-05-28T15:13:30Z', - } - - await expect(() => - new MemberService(mockIServiceOptions).upsert(member1), - ).rejects.toThrowError(new Error400()) - }) - - it('Should create non existent member - attributes with matching platform', async () => { - const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db) - - const mas = new MemberAttributeSettingsService(mockIServiceOptions) - - await mas.createPredefined(GITHUB_MEMBER_ATTRIBUTES) - await mas.createPredefined(TWITTER_MEMBER_ATTRIBUTES) - await mas.createPredefined(DISCORD_MEMBER_ATTRIBUTES) - - const member1 = { - username: 'anil', - platform: PlatformType.GITHUB, - emails: ['lala@l.com'], - score: 10, - attributes: { - [MemberAttributeName.IS_HIREABLE]: { - [PlatformType.GITHUB]: true, - }, - [MemberAttributeName.URL]: { - [PlatformType.GITHUB]: 'https://github.com/imcvampire', - [PlatformType.TWITTER]: 'https://some-twitter-url', - }, - [MemberAttributeName.WEBSITE_URL]: { - [PlatformType.GITHUB]: 'https://imcvampire.js.org/', - }, - [MemberAttributeName.BIO]: { - [PlatformType.GITHUB]: 'Lazy geek', - }, - [MemberAttributeName.LOCATION]: { - [PlatformType.GITHUB]: 'Helsinki, Finland', - }, - [MemberAttributeName.SOURCE_ID]: { - [PlatformType.TWITTER]: '#twitterId', - [PlatformType.DISCORD]: '#discordId', - }, - [MemberAttributeName.AVATAR_URL]: { - [PlatformType.TWITTER]: 'https://some-image-url', - }, - }, - joinedAt: '2020-05-28T15:13:30Z', - } - - // Save some attributes since they get modified in the upsert function - const { platform, username, attributes } = member1 - - const memberCreated = await new MemberService(mockIServiceOptions).upsert(member1) - - memberCreated.createdAt = memberCreated.createdAt.toISOString().split('T')[0] - memberCreated.updatedAt = memberCreated.updatedAt.toISOString().split('T')[0] - - const memberExpected = { - id: memberCreated.id, - username: { - [platform]: [username], - }, - displayName: username, - attributes: { - [MemberAttributeName.SOURCE_ID]: { - [PlatformType.DISCORD]: attributes[MemberAttributeName.SOURCE_ID][PlatformType.DISCORD], - [PlatformType.TWITTER]: attributes[MemberAttributeName.SOURCE_ID][PlatformType.TWITTER], - default: attributes[MemberAttributeName.SOURCE_ID][PlatformType.TWITTER], - }, - [MemberAttributeName.AVATAR_URL]: { - [PlatformType.TWITTER]: - attributes[MemberAttributeName.AVATAR_URL][PlatformType.TWITTER], - default: attributes[MemberAttributeName.AVATAR_URL][PlatformType.TWITTER], - }, - [MemberAttributeName.IS_HIREABLE]: { - [PlatformType.GITHUB]: attributes[MemberAttributeName.IS_HIREABLE][PlatformType.GITHUB], - default: attributes[MemberAttributeName.IS_HIREABLE][PlatformType.GITHUB], - }, - [MemberAttributeName.URL]: { - [PlatformType.GITHUB]: attributes[MemberAttributeName.URL][PlatformType.GITHUB], - [PlatformType.TWITTER]: attributes[MemberAttributeName.URL][PlatformType.TWITTER], - default: attributes[MemberAttributeName.URL][PlatformType.TWITTER], - }, - [MemberAttributeName.WEBSITE_URL]: { - [PlatformType.GITHUB]: attributes[MemberAttributeName.WEBSITE_URL][PlatformType.GITHUB], - default: attributes[MemberAttributeName.WEBSITE_URL][PlatformType.GITHUB], - }, - [MemberAttributeName.BIO]: { - [PlatformType.GITHUB]: attributes[MemberAttributeName.BIO][PlatformType.GITHUB], - default: attributes[MemberAttributeName.BIO][PlatformType.GITHUB], - }, - [MemberAttributeName.LOCATION]: { - [PlatformType.GITHUB]: attributes[MemberAttributeName.LOCATION][PlatformType.GITHUB], - default: attributes[MemberAttributeName.LOCATION][PlatformType.GITHUB], - }, - }, - emails: member1.emails, - score: member1.score, - importHash: null, - createdAt: SequelizeTestUtils.getNowWithoutTime(), - updatedAt: SequelizeTestUtils.getNowWithoutTime(), - deletedAt: null, - organizations: [ - { - displayName: 'l.com', - id: memberCreated.organizations[0].id, - memberOrganizations: { - memberId: memberCreated.id, - organizationId: memberCreated.organizations[0].id, - dateEnd: null, - dateStart: null, - title: null, - source: null, - }, - }, - ], - tenantId: mockIServiceOptions.currentTenant.id, - segments: mockIServiceOptions.currentSegments, - createdById: mockIServiceOptions.currentUser.id, - updatedById: mockIServiceOptions.currentUser.id, - reach: { total: -1 }, - joinedAt: new Date('2020-05-28T15:13:30Z'), - lastEnriched: null, - enrichedBy: [], - contributions: null, - affiliations: [], - manuallyCreated: false, - } - - expect(memberCreated).toStrictEqual(memberExpected) - }) - - it('Should create non existent member - object type username', async () => { - const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db) - const mas = new MemberAttributeSettingsService(mockIServiceOptions) - - await mas.createPredefined(GITHUB_MEMBER_ATTRIBUTES) - - const member1 = { - username: { - [PlatformType.GITHUB]: 'anil', - [PlatformType.TWITTER]: 'anil_twitter', - }, - platform: PlatformType.GITHUB, - emails: ['lala@l.com'], - score: 10, - attributes: { - [MemberAttributeName.IS_HIREABLE]: { - [PlatformType.GITHUB]: true, - }, - [MemberAttributeName.URL]: { - [PlatformType.GITHUB]: 'https://github.com/imcvampire', - }, - [MemberAttributeName.WEBSITE_URL]: { - [PlatformType.GITHUB]: 'https://imcvampire.js.org/', - }, - [MemberAttributeName.BIO]: { - [PlatformType.GITHUB]: 'Lazy geek', - }, - [MemberAttributeName.LOCATION]: { - [PlatformType.GITHUB]: 'Helsinki, Finland', - }, - }, - joinedAt: '2020-05-28T15:13:30Z', - } - - // Save some attributes since they get modified in the upsert function - const { username, attributes } = member1 - - const memberCreated = await new MemberService(mockIServiceOptions).upsert(member1) - - memberCreated.createdAt = memberCreated.createdAt.toISOString().split('T')[0] - memberCreated.updatedAt = memberCreated.updatedAt.toISOString().split('T')[0] - - const memberExpected = { - id: memberCreated.id, - username: { - [PlatformType.GITHUB]: ['anil'], - [PlatformType.TWITTER]: ['anil_twitter'], - }, - displayName: 'anil', - attributes: { - [MemberAttributeName.IS_HIREABLE]: { - [PlatformType.GITHUB]: attributes[MemberAttributeName.IS_HIREABLE][PlatformType.GITHUB], - default: attributes[MemberAttributeName.IS_HIREABLE][PlatformType.GITHUB], - }, - [MemberAttributeName.URL]: { - [PlatformType.GITHUB]: attributes[MemberAttributeName.URL][PlatformType.GITHUB], - default: attributes[MemberAttributeName.URL][PlatformType.GITHUB], - }, - [MemberAttributeName.WEBSITE_URL]: { - [PlatformType.GITHUB]: attributes[MemberAttributeName.WEBSITE_URL][PlatformType.GITHUB], - default: attributes[MemberAttributeName.WEBSITE_URL][PlatformType.GITHUB], - }, - [MemberAttributeName.BIO]: { - [PlatformType.GITHUB]: attributes[MemberAttributeName.BIO][PlatformType.GITHUB], - default: attributes[MemberAttributeName.BIO][PlatformType.GITHUB], - }, - [MemberAttributeName.LOCATION]: { - [PlatformType.GITHUB]: attributes[MemberAttributeName.LOCATION][PlatformType.GITHUB], - default: attributes[MemberAttributeName.LOCATION][PlatformType.GITHUB], - }, - }, - emails: member1.emails, - score: member1.score, - importHash: null, - createdAt: SequelizeTestUtils.getNowWithoutTime(), - updatedAt: SequelizeTestUtils.getNowWithoutTime(), - deletedAt: null, - tenantId: mockIServiceOptions.currentTenant.id, - segments: mockIServiceOptions.currentSegments, - createdById: mockIServiceOptions.currentUser.id, - updatedById: mockIServiceOptions.currentUser.id, - lastEnriched: null, - organizations: [ - { - displayName: 'l.com', - id: memberCreated.organizations[0].id, - memberOrganizations: { - memberId: memberCreated.id, - organizationId: memberCreated.organizations[0].id, - dateEnd: null, - dateStart: null, - title: null, - source: null, - }, - }, - ], - enrichedBy: [], - contributions: null, - reach: { total: -1 }, - joinedAt: new Date('2020-05-28T15:13:30Z'), - affiliations: [], - manuallyCreated: false, - } - - expect(memberCreated).toStrictEqual(memberExpected) - }) - - it('Should create non existent member - reach as number', async () => { - const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db) - - const member1 = { - username: 'anil', - platform: PlatformType.GITHUB, - emails: ['lala@l.com'], - score: 10, - attributes: {}, - reach: 10, - bio: 'Computer Science', - joinedAt: '2020-05-28T15:13:30Z', - location: 'Istanbul', - } - - // Save some attributes since they get modified in the upsert function - const { platform, username } = member1 - - const memberCreated = await new MemberService(mockIServiceOptions).upsert(member1) - - memberCreated.createdAt = memberCreated.createdAt.toISOString().split('T')[0] - memberCreated.updatedAt = memberCreated.updatedAt.toISOString().split('T')[0] - - const memberExpected = { - id: memberCreated.id, - username: { - [platform]: [username], - }, - displayName: username, - attributes: {}, - emails: member1.emails, - lastEnriched: null, - organizations: [ - { - displayName: 'l.com', - id: memberCreated.organizations[0].id, - memberOrganizations: { - memberId: memberCreated.id, - organizationId: memberCreated.organizations[0].id, - dateEnd: null, - dateStart: null, - title: null, - source: null, - }, - }, - ], - enrichedBy: [], - contributions: null, - score: member1.score, - importHash: null, - createdAt: SequelizeTestUtils.getNowWithoutTime(), - updatedAt: SequelizeTestUtils.getNowWithoutTime(), - deletedAt: null, - tenantId: mockIServiceOptions.currentTenant.id, - segments: mockIServiceOptions.currentSegments, - createdById: mockIServiceOptions.currentUser.id, - updatedById: mockIServiceOptions.currentUser.id, - reach: { total: 10, [PlatformType.GITHUB]: 10 }, - joinedAt: new Date('2020-05-28T15:13:30Z'), - affiliations: [], - manuallyCreated: false, - } - - expect(memberCreated).toStrictEqual(memberExpected) - }) - - it('Should create non existent member - reach as object, platform in object', async () => { - const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db) - - const member1 = { - username: 'anil', - platform: PlatformType.GITHUB, - emails: ['lala@l.com'], - score: 10, - reach: { [PlatformType.GITHUB]: 10, [PlatformType.TWITTER]: 10 }, - bio: 'Computer Science', - joinedAt: '2020-05-28T15:13:30Z', - location: 'Istanbul', - } - - // Save some attributes since they get modified in the upsert function - const { platform, username } = member1 - - const memberCreated = await new MemberService(mockIServiceOptions).upsert(member1) - - memberCreated.createdAt = memberCreated.createdAt.toISOString().split('T')[0] - memberCreated.updatedAt = memberCreated.updatedAt.toISOString().split('T')[0] - - const memberExpected = { - id: memberCreated.id, - username: { - [platform]: [username], - }, - displayName: username, - attributes: {}, - lastEnriched: null, - organizations: [ - { - displayName: 'l.com', - id: memberCreated.organizations[0].id, - memberOrganizations: { - memberId: memberCreated.id, - organizationId: memberCreated.organizations[0].id, - dateEnd: null, - dateStart: null, - title: null, - source: null, - }, - }, - ], - enrichedBy: [], - contributions: null, - emails: member1.emails, - score: member1.score, - importHash: null, - createdAt: SequelizeTestUtils.getNowWithoutTime(), - updatedAt: SequelizeTestUtils.getNowWithoutTime(), - deletedAt: null, - tenantId: mockIServiceOptions.currentTenant.id, - segments: mockIServiceOptions.currentSegments, - createdById: mockIServiceOptions.currentUser.id, - updatedById: mockIServiceOptions.currentUser.id, - reach: { total: 20, [PlatformType.GITHUB]: 10, [PlatformType.TWITTER]: 10 }, - joinedAt: new Date('2020-05-28T15:13:30Z'), - affiliations: [], - manuallyCreated: false, - } - - expect(memberCreated).toStrictEqual(memberExpected) - }) - - it('Should create non existent member - reach as object, platform not in object', async () => { - const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db) - - const member1 = { - username: 'anil', - platform: PlatformType.GITHUB, - emails: ['lala@l.com'], - score: 10, - reach: { [PlatformType.DISCORD]: 10, [PlatformType.TWITTER]: 10 }, - bio: 'Computer Science', - joinedAt: '2020-05-28T15:13:30Z', - location: 'Istanbul', - } - - // Save some attributes since they get modified in the upsert function - const { platform, username } = member1 - - const memberCreated = await new MemberService(mockIServiceOptions).upsert(member1) - - memberCreated.createdAt = memberCreated.createdAt.toISOString().split('T')[0] - memberCreated.updatedAt = memberCreated.updatedAt.toISOString().split('T')[0] - - const memberExpected = { - id: memberCreated.id, - username: { - [platform]: [username], - }, - displayName: username, - attributes: {}, - emails: member1.emails, - score: member1.score, - lastEnriched: null, - organizations: [ - { - displayName: 'l.com', - id: memberCreated.organizations[0].id, - memberOrganizations: { - memberId: memberCreated.id, - organizationId: memberCreated.organizations[0].id, - dateEnd: null, - dateStart: null, - title: null, - source: null, - }, - }, - ], - enrichedBy: [], - contributions: null, - importHash: null, - createdAt: SequelizeTestUtils.getNowWithoutTime(), - updatedAt: SequelizeTestUtils.getNowWithoutTime(), - deletedAt: null, - tenantId: mockIServiceOptions.currentTenant.id, - segments: mockIServiceOptions.currentSegments, - createdById: mockIServiceOptions.currentUser.id, - updatedById: mockIServiceOptions.currentUser.id, - reach: { total: 20, [PlatformType.DISCORD]: 10, [PlatformType.TWITTER]: 10 }, - joinedAt: new Date('2020-05-28T15:13:30Z'), - affiliations: [], - manuallyCreated: false, - } - - expect(memberCreated).toStrictEqual(memberExpected) - }) - - it('Should create non existent member - organization as name, no enrichment', async () => { - const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db) - - const member1 = { - username: 'anil', - platform: PlatformType.GITHUB, - emails: ['lala@gmail.com'], - score: 10, - attributes: {}, - reach: 10, - bio: 'Computer Science', - organizations: ['crowd.dev'], - joinedAt: '2020-05-28T15:13:30Z', - location: 'Istanbul', - } - - const memberCreated = await new MemberService(mockIServiceOptions).upsert(member1) - - memberCreated.createdAt = memberCreated.createdAt.toISOString().split('T')[0] - memberCreated.updatedAt = memberCreated.updatedAt.toISOString().split('T')[0] - - const organization = (await OrganizationRepository.findAndCountAll({}, mockIServiceOptions)) - .rows[0] - - const foundMember = await MemberRepository.findById(memberCreated.id, mockIServiceOptions) - - const o1 = foundMember.organizations[0].get({ plain: true }) - delete o1.createdAt - delete o1.updatedAt - - expect(o1).toStrictEqual({ - id: organization.id, - displayName: 'crowd.dev', - github: null, - location: null, - website: null, - description: null, - emails: null, - phoneNumbers: null, - logo: null, - memberOrganizations: { - dateEnd: null, - dateStart: null, - title: null, - source: null, - }, - tags: null, - twitter: null, - linkedin: null, - crunchbase: null, - employees: null, - revenueRange: null, - importHash: null, - deletedAt: null, - tenantId: mockIServiceOptions.currentTenant.id, - createdById: mockIServiceOptions.currentUser.id, - updatedById: mockIServiceOptions.currentUser.id, - isTeamOrganization: false, - type: null, - ticker: null, - size: null, - naics: null, - lastEnrichedAt: null, - industry: null, - headline: null, - geoLocation: null, - founded: null, - employeeCountByCountry: null, - address: null, - profiles: null, - attributes: {}, - manuallyCreated: false, - affiliatedProfiles: null, - allSubsidiaries: null, - alternativeDomains: null, - alternativeNames: null, - averageEmployeeTenure: null, - averageTenureByLevel: null, - averageTenureByRole: null, - directSubsidiaries: null, - employeeChurnRate: null, - employeeCountByMonth: null, - employeeGrowthRate: null, - employeeCountByMonthByLevel: null, - employeeCountByMonthByRole: null, - gicsSector: null, - grossAdditionsByMonth: null, - grossDeparturesByMonth: null, - ultimateParent: null, - immediateParent: null, - }) - }) - - it('Should create non existent member - organization as object, no enrichment', async () => { - const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db) - - const member1 = { - username: 'anil', - platform: PlatformType.GITHUB, - emails: ['lala@gmail.com'], - score: 10, - attributes: {}, - reach: 10, - bio: 'Computer Science', - organizations: [{ name: 'crowd.dev', url: 'https://crowd.dev', description: 'Here' }], - joinedAt: '2020-05-28T15:13:30Z', - location: 'Istanbul', - } - - const memberCreated = await new MemberService(mockIServiceOptions).upsert(member1) - - memberCreated.createdAt = memberCreated.createdAt.toISOString().split('T')[0] - memberCreated.updatedAt = memberCreated.updatedAt.toISOString().split('T')[0] - - const organization = (await OrganizationRepository.findAndCountAll({}, mockIServiceOptions)) - .rows[0] - - const foundMember = await MemberRepository.findById(memberCreated.id, mockIServiceOptions) - - const o1 = foundMember.organizations[0].get({ plain: true }) - delete o1.createdAt - delete o1.updatedAt - - expect(o1).toStrictEqual({ - id: organization.id, - displayName: 'crowd.dev', - github: null, - location: null, - website: null, - description: 'Here', - emails: null, - phoneNumbers: null, - logo: null, - memberOrganizations: { - dateEnd: null, - dateStart: null, - title: null, - source: null, - }, - tags: null, - twitter: null, - linkedin: null, - crunchbase: null, - employees: null, - revenueRange: null, - importHash: null, - deletedAt: null, - tenantId: mockIServiceOptions.currentTenant.id, - createdById: mockIServiceOptions.currentUser.id, - updatedById: mockIServiceOptions.currentUser.id, - isTeamOrganization: false, - type: null, - ticker: null, - size: null, - naics: null, - lastEnrichedAt: null, - industry: null, - headline: null, - geoLocation: null, - founded: null, - employeeCountByCountry: null, - address: null, - profiles: null, - attributes: {}, - manuallyCreated: false, - affiliatedProfiles: null, - allSubsidiaries: null, - alternativeDomains: null, - alternativeNames: null, - averageEmployeeTenure: null, - averageTenureByLevel: null, - averageTenureByRole: null, - directSubsidiaries: null, - employeeChurnRate: null, - employeeCountByMonth: null, - employeeGrowthRate: null, - employeeCountByMonthByLevel: null, - employeeCountByMonthByRole: null, - gicsSector: null, - grossAdditionsByMonth: null, - grossDeparturesByMonth: null, - ultimateParent: null, - immediateParent: null, - }) - }) - - it('Should create non existent member - organization as id', async () => { - const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db) - - const oCreated = await new OrganizationService(mockIServiceOptions).createOrUpdate({ - identities: [ - { - name: 'crowd.dev', - platform: 'crowd', - }, - ], - }) - - const member1 = { - username: 'anil', - platform: PlatformType.GITHUB, - emails: ['lala@gmail.com'], - score: 10, - attributes: {}, - reach: 10, - bio: 'Computer Science', - organizations: [oCreated.id], - joinedAt: '2020-05-28T15:13:30Z', - location: 'Istanbul', - } - - const memberCreated = await new MemberService(mockIServiceOptions).upsert(member1) - - memberCreated.createdAt = memberCreated.createdAt.toISOString().split('T')[0] - memberCreated.updatedAt = memberCreated.updatedAt.toISOString().split('T')[0] - - const organization = (await OrganizationRepository.findAndCountAll({}, mockIServiceOptions)) - .rows[0] - - const foundMember = await MemberRepository.findById(memberCreated.id, mockIServiceOptions) - - const o1 = foundMember.organizations[0].get({ plain: true }) - delete o1.createdAt - delete o1.updatedAt - - expect(o1).toStrictEqual({ - id: organization.id, - displayName: 'crowd.dev', - github: null, - location: null, - website: null, - description: null, - emails: null, - phoneNumbers: null, - logo: null, - memberOrganizations: { - dateEnd: null, - dateStart: null, - title: null, - source: null, - }, - tags: null, - twitter: null, - linkedin: null, - crunchbase: null, - employees: null, - revenueRange: null, - importHash: null, - deletedAt: null, - tenantId: mockIServiceOptions.currentTenant.id, - createdById: mockIServiceOptions.currentUser.id, - updatedById: mockIServiceOptions.currentUser.id, - isTeamOrganization: false, - type: null, - ticker: null, - size: null, - naics: null, - lastEnrichedAt: null, - industry: null, - headline: null, - geoLocation: null, - founded: null, - employeeCountByCountry: null, - address: null, - profiles: null, - attributes: {}, - manuallyCreated: false, - affiliatedProfiles: null, - allSubsidiaries: null, - alternativeDomains: null, - alternativeNames: null, - averageEmployeeTenure: null, - averageTenureByLevel: null, - averageTenureByRole: null, - directSubsidiaries: null, - employeeChurnRate: null, - employeeCountByMonth: null, - employeeGrowthRate: null, - employeeCountByMonthByLevel: null, - employeeCountByMonthByRole: null, - gicsSector: null, - grossAdditionsByMonth: null, - grossDeparturesByMonth: null, - ultimateParent: null, - immediateParent: null, - }) - }) - - it('Should update existent member succesfully - simple', async () => { - const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db) - - const mas = new MemberAttributeSettingsService(mockIServiceOptions) - - await mas.createPredefined(GITHUB_MEMBER_ATTRIBUTES) - - const member1 = { - username: 'anil', - emails: ['lala@l.com'], - platform: PlatformType.GITHUB, - score: 10, - attributes: { - [MemberAttributeName.IS_HIREABLE]: { - [PlatformType.GITHUB]: true, - }, - [MemberAttributeName.URL]: { - [PlatformType.GITHUB]: 'https://github.com/imcvampire', - }, - [MemberAttributeName.WEBSITE_URL]: { - [PlatformType.GITHUB]: 'https://imcvampire.js.org/', - }, - [MemberAttributeName.BIO]: { - [PlatformType.GITHUB]: 'Lazy geek', - }, - [MemberAttributeName.LOCATION]: { - [PlatformType.GITHUB]: 'Helsinki, Finland', - }, - }, - joinedAt: '2020-05-28T15:13:30Z', - } - - const member1Username = member1.username - const attributes = member1.attributes - - const memberCreated = await new MemberService(mockIServiceOptions).upsert(member1) - - memberCreated.createdAt = memberCreated.createdAt.toISOString().split('T')[0] - memberCreated.updatedAt = memberCreated.updatedAt.toISOString().split('T')[0] - - const member2 = { - username: 'anil', - emails: ['test@gmail.com', 'test2@yahoo.com'], - platform: PlatformType.GITHUB, - location: 'Ankara', - } - - const memberUpdated = await new MemberService(mockIServiceOptions).upsert(member2) - - memberUpdated.createdAt = memberUpdated.createdAt.toISOString().split('T')[0] - memberUpdated.updatedAt = memberUpdated.updatedAt.toISOString().split('T')[0] - - const memberExpected = { - id: memberCreated.id, - username: { - [PlatformType.GITHUB]: [member1Username], - }, - displayName: member1Username, - attributes: { - [MemberAttributeName.IS_HIREABLE]: { - [PlatformType.GITHUB]: attributes[MemberAttributeName.IS_HIREABLE][PlatformType.GITHUB], - default: attributes[MemberAttributeName.IS_HIREABLE][PlatformType.GITHUB], - }, - [MemberAttributeName.URL]: { - [PlatformType.GITHUB]: attributes[MemberAttributeName.URL][PlatformType.GITHUB], - default: attributes[MemberAttributeName.URL][PlatformType.GITHUB], - }, - [MemberAttributeName.WEBSITE_URL]: { - [PlatformType.GITHUB]: attributes[MemberAttributeName.WEBSITE_URL][PlatformType.GITHUB], - default: attributes[MemberAttributeName.WEBSITE_URL][PlatformType.GITHUB], - }, - [MemberAttributeName.BIO]: { - [PlatformType.GITHUB]: attributes[MemberAttributeName.BIO][PlatformType.GITHUB], - default: attributes[MemberAttributeName.BIO][PlatformType.GITHUB], - }, - [MemberAttributeName.LOCATION]: { - [PlatformType.GITHUB]: attributes[MemberAttributeName.LOCATION][PlatformType.GITHUB], - default: attributes[MemberAttributeName.LOCATION][PlatformType.GITHUB], - }, - }, - lastEnriched: null, - organizations: [ - { - displayName: 'l.com', - id: memberCreated.organizations[0].id, - memberOrganizations: { - memberId: memberCreated.id, - organizationId: memberCreated.organizations[0].id, - dateEnd: null, - dateStart: null, - title: null, - source: null, - }, - }, - ], - enrichedBy: [], - contributions: null, - emails: ['lala@l.com', 'test@gmail.com', 'test2@yahoo.com'], - score: member1.score, - importHash: null, - createdAt: SequelizeTestUtils.getNowWithoutTime(), - updatedAt: SequelizeTestUtils.getNowWithoutTime(), - deletedAt: null, - tenantId: mockIServiceOptions.currentTenant.id, - segments: mockIServiceOptions.currentSegments, - createdById: mockIServiceOptions.currentUser.id, - updatedById: mockIServiceOptions.currentUser.id, - joinedAt: new Date('2020-05-28T15:13:30Z'), - reach: { total: -1 }, - affiliations: [], - manuallyCreated: false, - } - - expect(memberUpdated).toStrictEqual(memberExpected) - }) - - it('Should update existent member successfully - attributes with matching platform', async () => { - const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db) - - const mas = new MemberAttributeSettingsService(mockIServiceOptions) - - await mas.createPredefined(GITHUB_MEMBER_ATTRIBUTES) - await mas.createPredefined(TWITTER_MEMBER_ATTRIBUTES) - - const member1 = { - username: 'anil', - emails: ['lala@l.com'], - platform: PlatformType.GITHUB, - score: 10, - attributes: { - [MemberAttributeName.IS_HIREABLE]: { - [PlatformType.GITHUB]: true, - }, - [MemberAttributeName.URL]: { - [PlatformType.GITHUB]: 'https://github.com/imcvampire', - }, - }, - joinedAt: '2020-05-28T15:13:30Z', - } - - const member1Username = member1.username - const attributes1 = member1.attributes - - const memberCreated = await new MemberService(mockIServiceOptions).upsert(member1) - - memberCreated.createdAt = memberCreated.createdAt.toISOString().split('T')[0] - memberCreated.updatedAt = memberCreated.updatedAt.toISOString().split('T')[0] - - const member2 = { - username: 'anil', - platform: PlatformType.GITHUB, - attributes: { - [MemberAttributeName.WEBSITE_URL]: { - [PlatformType.GITHUB]: 'https://imcvampire.js.org/', - }, - [MemberAttributeName.BIO]: { - [PlatformType.GITHUB]: 'Lazy geek', - }, - [MemberAttributeName.LOCATION]: { - [PlatformType.GITHUB]: 'Helsinki, Finland', - }, - [MemberAttributeName.URL]: { - [PlatformType.TWITTER]: 'https://twitter-url', - }, - }, - } - - const attributes2 = member2.attributes - - const memberUpdated = await new MemberService(mockIServiceOptions).upsert(member2) - - memberUpdated.createdAt = memberUpdated.createdAt.toISOString().split('T')[0] - memberUpdated.updatedAt = memberUpdated.updatedAt.toISOString().split('T')[0] - - const memberExpected = { - id: memberCreated.id, - username: { - [PlatformType.GITHUB]: [member1Username], - }, - displayName: member1Username, - attributes: { - [MemberAttributeName.IS_HIREABLE]: { - [PlatformType.GITHUB]: - attributes1[MemberAttributeName.IS_HIREABLE][PlatformType.GITHUB], - default: attributes1[MemberAttributeName.IS_HIREABLE][PlatformType.GITHUB], - }, - [MemberAttributeName.URL]: { - [PlatformType.GITHUB]: attributes1[MemberAttributeName.URL][PlatformType.GITHUB], - [PlatformType.TWITTER]: attributes2[MemberAttributeName.URL][PlatformType.TWITTER], - default: attributes2[MemberAttributeName.URL][PlatformType.TWITTER], - }, - [MemberAttributeName.WEBSITE_URL]: { - [PlatformType.GITHUB]: - attributes2[MemberAttributeName.WEBSITE_URL][PlatformType.GITHUB], - default: attributes2[MemberAttributeName.WEBSITE_URL][PlatformType.GITHUB], - }, - [MemberAttributeName.BIO]: { - [PlatformType.GITHUB]: attributes2[MemberAttributeName.BIO][PlatformType.GITHUB], - default: attributes2[MemberAttributeName.BIO][PlatformType.GITHUB], - }, - [MemberAttributeName.LOCATION]: { - [PlatformType.GITHUB]: attributes2[MemberAttributeName.LOCATION][PlatformType.GITHUB], - default: attributes2[MemberAttributeName.LOCATION][PlatformType.GITHUB], - }, - }, - lastEnriched: null, - organizations: [ - { - displayName: 'l.com', - id: memberCreated.organizations[0].id, - memberOrganizations: { - memberId: memberCreated.id, - organizationId: memberCreated.organizations[0].id, - dateEnd: null, - dateStart: null, - title: null, - source: null, - }, - }, - ], - enrichedBy: [], - contributions: null, - emails: member1.emails, - score: member1.score, - importHash: null, - createdAt: SequelizeTestUtils.getNowWithoutTime(), - updatedAt: SequelizeTestUtils.getNowWithoutTime(), - deletedAt: null, - tenantId: mockIServiceOptions.currentTenant.id, - segments: mockIServiceOptions.currentSegments, - createdById: mockIServiceOptions.currentUser.id, - updatedById: mockIServiceOptions.currentUser.id, - joinedAt: new Date('2020-05-28T15:13:30Z'), - reach: { total: -1 }, - affiliations: [], - manuallyCreated: false, - } - - expect(memberUpdated).toStrictEqual(memberExpected) - }) - - it('Should update existent member succesfully - object type username', async () => { - const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db) - - const mas = new MemberAttributeSettingsService(mockIServiceOptions) - - await mas.createPredefined(GITHUB_MEMBER_ATTRIBUTES) - - const member1 = { - username: 'anil', - emails: ['lala@l.com'], - platform: PlatformType.GITHUB, - score: 10, - attributes: { - [MemberAttributeName.IS_HIREABLE]: { - [PlatformType.GITHUB]: true, - }, - [MemberAttributeName.URL]: { - [PlatformType.GITHUB]: 'https://github.com/imcvampire', - }, - [MemberAttributeName.WEBSITE_URL]: { - [PlatformType.GITHUB]: 'https://imcvampire.js.org/', - }, - [MemberAttributeName.BIO]: { - [PlatformType.GITHUB]: 'Lazy geek', - }, - [MemberAttributeName.LOCATION]: { - [PlatformType.GITHUB]: 'Helsinki, Finland', - }, - }, - joinedAt: '2020-05-28T15:13:30Z', - } - - const member1Username = member1.username - const attributes = member1.attributes - - const memberCreated = await new MemberService(mockIServiceOptions).upsert(member1) - - memberCreated.createdAt = memberCreated.createdAt.toISOString().split('T')[0] - memberCreated.updatedAt = memberCreated.updatedAt.toISOString().split('T')[0] - - const member2 = { - username: { - [PlatformType.GITHUB]: 'anil', - [PlatformType.TWITTER]: 'anil_twitter', - [PlatformType.DISCORD]: 'anil_discord', - }, - platform: PlatformType.GITHUB, - } - - const memberUpdated = await new MemberService(mockIServiceOptions).upsert(member2) - - memberUpdated.createdAt = memberUpdated.createdAt.toISOString().split('T')[0] - memberUpdated.updatedAt = memberUpdated.updatedAt.toISOString().split('T')[0] - - const memberExpected = { - id: memberCreated.id, - username: { - [PlatformType.GITHUB]: ['anil'], - [PlatformType.TWITTER]: ['anil_twitter'], - [PlatformType.DISCORD]: ['anil_discord'], - }, - displayName: 'anil', - attributes: { - [MemberAttributeName.IS_HIREABLE]: { - [PlatformType.GITHUB]: attributes[MemberAttributeName.IS_HIREABLE][PlatformType.GITHUB], - default: attributes[MemberAttributeName.IS_HIREABLE][PlatformType.GITHUB], - }, - [MemberAttributeName.URL]: { - [PlatformType.GITHUB]: attributes[MemberAttributeName.URL][PlatformType.GITHUB], - default: attributes[MemberAttributeName.URL][PlatformType.GITHUB], - }, - [MemberAttributeName.WEBSITE_URL]: { - [PlatformType.GITHUB]: attributes[MemberAttributeName.WEBSITE_URL][PlatformType.GITHUB], - default: attributes[MemberAttributeName.WEBSITE_URL][PlatformType.GITHUB], - }, - [MemberAttributeName.BIO]: { - [PlatformType.GITHUB]: attributes[MemberAttributeName.BIO][PlatformType.GITHUB], - default: attributes[MemberAttributeName.BIO][PlatformType.GITHUB], - }, - [MemberAttributeName.LOCATION]: { - [PlatformType.GITHUB]: attributes[MemberAttributeName.LOCATION][PlatformType.GITHUB], - default: attributes[MemberAttributeName.LOCATION][PlatformType.GITHUB], - }, - }, - emails: member1.emails, - lastEnriched: null, - organizations: [ - { - displayName: 'l.com', - id: memberCreated.organizations[0].id, - memberOrganizations: { - memberId: memberCreated.id, - organizationId: memberCreated.organizations[0].id, - dateEnd: null, - dateStart: null, - title: null, - source: null, - }, - }, - ], - enrichedBy: [], - contributions: null, - score: member1.score, - importHash: null, - createdAt: SequelizeTestUtils.getNowWithoutTime(), - updatedAt: SequelizeTestUtils.getNowWithoutTime(), - deletedAt: null, - tenantId: mockIServiceOptions.currentTenant.id, - segments: mockIServiceOptions.currentSegments, - createdById: mockIServiceOptions.currentUser.id, - updatedById: mockIServiceOptions.currentUser.id, - joinedAt: new Date('2020-05-28T15:13:30Z'), - reach: { total: -1 }, - affiliations: [], - manuallyCreated: false, - } - - expect(memberUpdated).toStrictEqual(memberExpected) - }) - - it('Should throw 400 error when given platform does not match with username object ', async () => { - const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db) - const mas = new MemberAttributeSettingsService(mockIServiceOptions) - - await mas.createPredefined(GITHUB_MEMBER_ATTRIBUTES) - - const member1 = { - username: 'anil', - emails: ['lala@l.com'], - platform: PlatformType.GITHUB, - score: 10, - attributes: { - [MemberAttributeName.IS_HIREABLE]: { - [PlatformType.GITHUB]: true, - }, - [MemberAttributeName.URL]: { - [PlatformType.GITHUB]: 'https://github.com/imcvampire', - }, - [MemberAttributeName.WEBSITE_URL]: { - [PlatformType.GITHUB]: 'https://imcvampire.js.org/', - }, - [MemberAttributeName.BIO]: { - [PlatformType.GITHUB]: 'Lazy geek', - }, - [MemberAttributeName.LOCATION]: { - [PlatformType.GITHUB]: 'Helsinki, Finland', - }, - }, - joinedAt: '2020-05-28T15:13:30Z', - } - - const memberCreated = await new MemberService(mockIServiceOptions).upsert(member1) - - memberCreated.createdAt = memberCreated.createdAt.toISOString().split('T')[0] - memberCreated.updatedAt = memberCreated.updatedAt.toISOString().split('T')[0] - - const member2 = { - username: { - [PlatformType.GITHUB]: 'anil', - [PlatformType.TWITTER]: 'anil_twitter', - [PlatformType.DISCORD]: 'anil_discord', - }, - platform: PlatformType.SLACK, - } - - await expect(() => - new MemberService(mockIServiceOptions).upsert(member2), - ).rejects.toThrowError(new Error400()) - }) - - it('Should update existent member succesfully - JSON fields', async () => { - const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db) - const mas = new MemberAttributeSettingsService(mockIServiceOptions) - - await mas.createPredefined(GITHUB_MEMBER_ATTRIBUTES) - await mas.createPredefined(DEVTO_MEMBER_ATTRIBUTES) - - const member1 = { - username: 'anil', - platform: PlatformType.TWITTER, - emails: ['lala@l.com'], - score: 10, - attributes: { - [MemberAttributeName.IS_HIREABLE]: { - [PlatformType.GITHUB]: true, - }, - [MemberAttributeName.URL]: { - [PlatformType.GITHUB]: 'https://github.com/imcvampire', - }, - [MemberAttributeName.WEBSITE_URL]: { - [PlatformType.GITHUB]: 'https://imcvampire.js.org/', - }, - [MemberAttributeName.BIO]: { - [PlatformType.GITHUB]: 'Lazy geek', - }, - [MemberAttributeName.LOCATION]: { - [PlatformType.GITHUB]: 'Helsinki, Finland', - }, - }, - joinedAt: '2020-05-28T15:13:30Z', - } - - const member1Username = member1.username - const attributes1 = member1.attributes - - const memberCreated = await new MemberService(mockIServiceOptions).upsert(member1) - - memberCreated.createdAt = memberCreated.createdAt.toISOString().split('T')[0] - memberCreated.updatedAt = memberCreated.updatedAt.toISOString().split('T')[0] - - const member2 = { - username: 'anil', - platform: PlatformType.TWITTER, - joinedAt: '2020-05-28T15:13:30Z', - location: 'Ankara', - attributes: { - [MemberAttributeName.SOURCE_ID]: { - [PlatformType.DEVTO]: '#someDevtoId', - [PlatformType.SLACK]: '#someSlackId', - }, - [MemberAttributeName.NAME]: { - [PlatformType.DEVTO]: 'Michael Scott', - }, - [MemberAttributeName.URL]: { - [PlatformType.DEVTO]: 'https://some-devto-url', - }, - }, - } - - const attributes2 = member2.attributes - - const memberUpdated = await new MemberService(mockIServiceOptions).upsert(member2) - - memberUpdated.createdAt = memberUpdated.createdAt.toISOString().split('T')[0] - memberUpdated.updatedAt = memberUpdated.updatedAt.toISOString().split('T')[0] - - const memberExpected = { - id: memberCreated.id, - joinedAt: new Date('2020-05-28T15:13:30Z'), - username: { - [PlatformType.TWITTER]: [member1Username], - }, - displayName: member1Username, - attributes: { - [MemberAttributeName.SOURCE_ID]: { - [PlatformType.DEVTO]: attributes2[MemberAttributeName.SOURCE_ID][PlatformType.DEVTO], - [PlatformType.SLACK]: attributes2[MemberAttributeName.SOURCE_ID][PlatformType.SLACK], - default: attributes2[MemberAttributeName.SOURCE_ID][PlatformType.DEVTO], - }, - [MemberAttributeName.NAME]: { - [PlatformType.DEVTO]: attributes2[MemberAttributeName.NAME][PlatformType.DEVTO], - default: attributes2[MemberAttributeName.NAME][PlatformType.DEVTO], - }, - [MemberAttributeName.IS_HIREABLE]: { - [PlatformType.GITHUB]: - attributes1[MemberAttributeName.IS_HIREABLE][PlatformType.GITHUB], - default: attributes1[MemberAttributeName.IS_HIREABLE][PlatformType.GITHUB], - }, - [MemberAttributeName.URL]: { - [PlatformType.GITHUB]: attributes1[MemberAttributeName.URL][PlatformType.GITHUB], - [PlatformType.DEVTO]: attributes2[MemberAttributeName.URL][PlatformType.DEVTO], - default: attributes1[MemberAttributeName.URL][PlatformType.GITHUB], - }, - [MemberAttributeName.WEBSITE_URL]: { - [PlatformType.GITHUB]: - attributes1[MemberAttributeName.WEBSITE_URL][PlatformType.GITHUB], - default: attributes1[MemberAttributeName.WEBSITE_URL][PlatformType.GITHUB], - }, - [MemberAttributeName.BIO]: { - [PlatformType.GITHUB]: attributes1[MemberAttributeName.BIO][PlatformType.GITHUB], - default: attributes1[MemberAttributeName.BIO][PlatformType.GITHUB], - }, - [MemberAttributeName.LOCATION]: { - [PlatformType.GITHUB]: attributes1[MemberAttributeName.LOCATION][PlatformType.GITHUB], - default: attributes1[MemberAttributeName.LOCATION][PlatformType.GITHUB], - }, - }, - emails: member1.emails, - lastEnriched: null, - organizations: [ - { - displayName: 'l.com', - id: memberCreated.organizations[0].id, - memberOrganizations: { - memberId: memberCreated.id, - organizationId: memberCreated.organizations[0].id, - dateEnd: null, - dateStart: null, - title: null, - source: null, - }, - }, - ], - enrichedBy: [], - contributions: null, - score: member1.score, - importHash: null, - createdAt: SequelizeTestUtils.getNowWithoutTime(), - updatedAt: SequelizeTestUtils.getNowWithoutTime(), - deletedAt: null, - tenantId: mockIServiceOptions.currentTenant.id, - segments: mockIServiceOptions.currentSegments, - createdById: mockIServiceOptions.currentUser.id, - updatedById: mockIServiceOptions.currentUser.id, - reach: { total: -1 }, - affiliations: [], - manuallyCreated: false, - } - - expect(memberUpdated).toStrictEqual(memberExpected) - }) - - it('Should update existent member succesfully - reach from default to complete - sending number', async () => { - const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db) - - const member1 = { - username: 'anil', - platform: PlatformType.GITHUB, - joinedAt: '2020-05-28T15:13:30Z', - } - - const member1Username = member1.username - - const memberCreated = await new MemberService(mockIServiceOptions).upsert(member1) - - memberCreated.createdAt = memberCreated.createdAt.toISOString().split('T')[0] - memberCreated.updatedAt = memberCreated.updatedAt.toISOString().split('T')[0] - - const member2 = { - username: 'anil', - platform: PlatformType.GITHUB, - reach: 10, - } - - const memberUpdated = await new MemberService(mockIServiceOptions).upsert(member2) - - memberUpdated.createdAt = memberUpdated.createdAt.toISOString().split('T')[0] - memberUpdated.updatedAt = memberUpdated.updatedAt.toISOString().split('T')[0] - - const memberExpected = { - id: memberCreated.id, - joinedAt: new Date('2020-05-28T15:13:30Z'), - username: { - [PlatformType.GITHUB]: [member1Username], - }, - displayName: member1Username, - lastEnriched: null, - organizations: [], - enrichedBy: [], - contributions: null, - reach: { total: 10, [PlatformType.GITHUB]: 10 }, - importHash: null, - createdAt: SequelizeTestUtils.getNowWithoutTime(), - updatedAt: SequelizeTestUtils.getNowWithoutTime(), - deletedAt: null, - tenantId: mockIServiceOptions.currentTenant.id, - segments: mockIServiceOptions.currentSegments, - createdById: mockIServiceOptions.currentUser.id, - updatedById: mockIServiceOptions.currentUser.id, - score: -1, - emails: [], - attributes: {}, - affiliations: [], - manuallyCreated: false, - } - - expect(memberUpdated).toStrictEqual(memberExpected) - }) - - it('Should update existent member succesfully - reach from default to complete - sending platform', async () => { - const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db) - - const member1 = { - username: 'anil', - type: 'member', - platform: PlatformType.GITHUB, - joinedAt: '2020-05-28T15:13:30Z', - } - - const member1Username = member1.username - - const memberCreated = await new MemberService(mockIServiceOptions).upsert(member1) - - memberCreated.createdAt = memberCreated.createdAt.toISOString().split('T')[0] - memberCreated.updatedAt = memberCreated.updatedAt.toISOString().split('T')[0] - - const member2 = { - username: 'anil', - platform: PlatformType.GITHUB, - reach: { [PlatformType.GITHUB]: 10 }, - } - - const memberUpdated = await new MemberService(mockIServiceOptions).upsert(member2) - - memberUpdated.createdAt = memberUpdated.createdAt.toISOString().split('T')[0] - memberUpdated.updatedAt = memberUpdated.updatedAt.toISOString().split('T')[0] - - const memberExpected = { - id: memberCreated.id, - joinedAt: new Date('2020-05-28T15:13:30Z'), - username: { - [PlatformType.GITHUB]: [member1Username], - }, - lastEnriched: null, - organizations: [], - enrichedBy: [], - contributions: null, - displayName: member1Username, - reach: { total: 10, [PlatformType.GITHUB]: 10 }, - importHash: null, - createdAt: SequelizeTestUtils.getNowWithoutTime(), - updatedAt: SequelizeTestUtils.getNowWithoutTime(), - deletedAt: null, - tenantId: mockIServiceOptions.currentTenant.id, - segments: mockIServiceOptions.currentSegments, - createdById: mockIServiceOptions.currentUser.id, - updatedById: mockIServiceOptions.currentUser.id, - score: -1, - emails: [], - attributes: {}, - affiliations: [], - manuallyCreated: false, - } - - expect(memberUpdated).toStrictEqual(memberExpected) - }) - - it('Should update existent member succesfully - complex reach update from object', async () => { - const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db) - - const member1 = { - username: 'anil', - type: 'member', - platform: PlatformType.GITHUB, - joinedAt: '2020-05-28T15:13:30Z', - reach: { [PlatformType.TWITTER]: 10, linkedin: 10, total: 20 }, - } - - const member1Username = member1.username - - const memberCreated = await new MemberService(mockIServiceOptions).upsert(member1) - - memberCreated.createdAt = memberCreated.createdAt.toISOString().split('T')[0] - memberCreated.updatedAt = memberCreated.updatedAt.toISOString().split('T')[0] - - const member2 = { - username: 'anil', - platform: PlatformType.GITHUB, - reach: { [PlatformType.GITHUB]: 15, linkedin: 11 }, - } - - const memberUpdated = await new MemberService(mockIServiceOptions).upsert(member2) - - memberUpdated.createdAt = memberUpdated.createdAt.toISOString().split('T')[0] - memberUpdated.updatedAt = memberUpdated.updatedAt.toISOString().split('T')[0] - - const memberExpected = { - id: memberCreated.id, - joinedAt: new Date('2020-05-28T15:13:30Z'), - username: { - [PlatformType.GITHUB]: [member1Username], - }, - lastEnriched: null, - organizations: [], - enrichedBy: [], - contributions: null, - displayName: member1Username, - reach: { total: 36, [PlatformType.GITHUB]: 15, linkedin: 11, [PlatformType.TWITTER]: 10 }, - importHash: null, - createdAt: SequelizeTestUtils.getNowWithoutTime(), - updatedAt: SequelizeTestUtils.getNowWithoutTime(), - deletedAt: null, - tenantId: mockIServiceOptions.currentTenant.id, - segments: mockIServiceOptions.currentSegments, - createdById: mockIServiceOptions.currentUser.id, - updatedById: mockIServiceOptions.currentUser.id, - score: -1, - emails: [], - attributes: {}, - affiliations: [], - manuallyCreated: false, - } - - expect(memberUpdated).toStrictEqual(memberExpected) - }) - - it('Should update existent member succesfully - complex reach update from number', async () => { - const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db) - - const member1 = { - username: 'anil', - type: 'member', - platform: PlatformType.GITHUB, - joinedAt: '2020-05-28T15:13:30Z', - reach: { [PlatformType.TWITTER]: 10, linkedin: 10, total: 20 }, - } - - const member1Username = member1.username - - const memberCreated = await new MemberService(mockIServiceOptions).upsert(member1) - - memberCreated.createdAt = memberCreated.createdAt.toISOString().split('T')[0] - memberCreated.updatedAt = memberCreated.updatedAt.toISOString().split('T')[0] - - const member2 = { - username: 'anil', - platform: PlatformType.GITHUB, - reach: 30, - } - - const memberUpdated = await new MemberService(mockIServiceOptions).upsert(member2) - - memberUpdated.createdAt = memberUpdated.createdAt.toISOString().split('T')[0] - memberUpdated.updatedAt = memberUpdated.updatedAt.toISOString().split('T')[0] - - const memberExpected = { - id: memberCreated.id, - joinedAt: new Date('2020-05-28T15:13:30Z'), - username: { - [PlatformType.GITHUB]: [member1Username], - }, - displayName: member1Username, - lastEnriched: null, - organizations: [], - enrichedBy: [], - contributions: null, - reach: { total: 50, [PlatformType.GITHUB]: 30, linkedin: 10, [PlatformType.TWITTER]: 10 }, - importHash: null, - createdAt: SequelizeTestUtils.getNowWithoutTime(), - updatedAt: SequelizeTestUtils.getNowWithoutTime(), - deletedAt: null, - tenantId: mockIServiceOptions.currentTenant.id, - segments: mockIServiceOptions.currentSegments, - createdById: mockIServiceOptions.currentUser.id, - updatedById: mockIServiceOptions.currentUser.id, - score: -1, - emails: [], - attributes: {}, - affiliations: [], - manuallyCreated: false, - } - - expect(memberUpdated).toStrictEqual(memberExpected) - }) - }) - - describe('update method', () => { - it('Should update existent member succesfully - removing identities with simple string format', async () => { - const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db) - - const member1 = { - username: 'anil', - type: 'member', - platform: PlatformType.GITHUB, - joinedAt: '2020-05-28T15:13:30Z', - } - - const memberCreated = await new MemberService(mockIServiceOptions).upsert(member1) - - const toUpdate = { - username: 'anil_new', - platform: PlatformType.GITHUB, - } - - const memberUpdated = await new MemberService(mockIServiceOptions).update( - memberCreated.id, - toUpdate, - ) - - expect(memberUpdated.username[PlatformType.GITHUB]).toStrictEqual(['anil_new']) - }) - - it('Should update existent member succesfully - removing identities with simple identity format', async () => { - const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db) - - const member1 = { - username: { - [PlatformType.GITHUB]: { - username: 'anil', - }, - }, - platform: PlatformType.GITHUB, - type: 'member', - joinedAt: '2020-05-28T15:13:30Z', - } - - const memberCreated = await new MemberService(mockIServiceOptions).upsert(member1) - - const toUpdate = { - username: { - [PlatformType.GITHUB]: { - username: 'anil_new', - }, - }, - platform: PlatformType.GITHUB, - } - - const memberUpdated = await new MemberService(mockIServiceOptions).update( - memberCreated.id, - toUpdate, - ) - - expect(memberUpdated.username[PlatformType.GITHUB]).toStrictEqual(['anil_new']) - }) - - it('Should update existent member succesfully - removing identities with array identity format', async () => { - const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db) - - const member1 = { - username: { - [PlatformType.GITHUB]: [ - { - username: 'anil', - }, - ], - }, - platform: PlatformType.GITHUB, - type: 'member', - joinedAt: '2020-05-28T15:13:30Z', - } - - const memberCreated = await new MemberService(mockIServiceOptions).upsert(member1) - - const toUpdate = { - username: { - [PlatformType.GITHUB]: [ - { - username: 'anil_new', - }, - { - username: 'anil_new2', - }, - ], - }, - platform: PlatformType.GITHUB, - } - - const memberUpdated = await new MemberService(mockIServiceOptions).update( - memberCreated.id, - toUpdate, - ) - - expect(memberUpdated.username[PlatformType.GITHUB]).toStrictEqual(['anil_new', 'anil_new2']) - }) - }) - - describe('merge method', () => { - it('Should merge', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - const mas = new MemberAttributeSettingsService(mockIRepositoryOptions) - - await mas.createPredefined(GITHUB_MEMBER_ATTRIBUTES) - await mas.createPredefined(DISCORD_MEMBER_ATTRIBUTES) - await mas.createPredefined(TWITTER_MEMBER_ATTRIBUTES) - await mas.createPredefined(SLACK_MEMBER_ATTRIBUTES) - - const memberService = new MemberService(mockIRepositoryOptions) - - let t1 = await TagRepository.create({ name: 'tag1' }, mockIRepositoryOptions) - let t2 = await TagRepository.create({ name: 'tag2' }, mockIRepositoryOptions) - let t3 = await TagRepository.create({ name: 'tag3' }, mockIRepositoryOptions) - - let o1 = await OrganizationRepository.create({ displayName: 'org1' }, mockIRepositoryOptions) - let o2 = await OrganizationRepository.create({ displayName: 'org2' }, mockIRepositoryOptions) - let o3 = await OrganizationRepository.create({ displayName: 'org3' }, mockIRepositoryOptions) - - let task1 = await TaskRepository.create({ name: 'task1' }, mockIRepositoryOptions) - let task2 = await TaskRepository.create({ name: 'task2' }, mockIRepositoryOptions) - let task3 = await TaskRepository.create({ name: 'task3' }, mockIRepositoryOptions) - - let note1 = await NoteRepository.create({ body: 'note1' }, mockIRepositoryOptions) - let note2 = await NoteRepository.create({ body: 'note2' }, mockIRepositoryOptions) - let note3 = await NoteRepository.create({ body: 'note3' }, mockIRepositoryOptions) - - const member1 = { - username: { - [PlatformType.GITHUB]: 'anil', - }, - displayName: 'Anil', - emails: ['anil+1@crowd.dev', 'anil+2@crowd.dev'], - joinedAt: '2021-05-27T15:14:30Z', - attributes: {}, - tags: [t1.id, t2.id], - organizations: [o1.id, o2.id], - tasks: [task1.id, task2.id], - notes: [note1.id, note2.id], - } - - const member2 = { - username: { - [PlatformType.DISCORD]: 'anil', - }, - emails: ['anil+1@crowd.dev', 'anil+3@crowd.dev'], - displayName: 'Anil', - joinedAt: '2021-05-30T15:14:30Z', - attributes: { - [MemberAttributeName.LOCATION]: { - [PlatformType.GITHUB]: 'Crowd.dev', - default: 'Crowd.dev', - }, - [MemberAttributeName.SOURCE_ID]: { - [PlatformType.DISCORD]: '#discordId', - default: '#discordId', - }, - }, - tags: [t2.id, t3.id], - organizations: [o2.id, o3.id], - tasks: [task2.id, task3.id], - notes: [note2.id, note3.id], - } - - const member3 = { - username: { - [PlatformType.TWITTER]: 'anil', - }, - displayName: 'Anil', - joinedAt: '2021-05-30T15:14:30Z', - attributes: { - [MemberAttributeName.URL]: { - [PlatformType.TWITTER]: 'https://a-twitter-url', - default: 'https://a-twitter-url', - }, - }, - } - const member4 = { - username: { - [PlatformType.SLACK]: 'testt', - }, - displayName: 'Member 4', - joinedAt: '2021-05-30T15:14:30Z', - attributes: { - [MemberAttributeName.SOURCE_ID]: { - [PlatformType.SLACK]: '#slackId', - default: '#slackId', - }, - }, - } - - const returnedMember1 = await MemberRepository.create(member1, mockIRepositoryOptions) - const returnedMember2 = await MemberRepository.create(member2, mockIRepositoryOptions) - const returnedMember3 = await MemberRepository.create(member3, mockIRepositoryOptions) - const returnedMember4 = await MemberRepository.create(member4, mockIRepositoryOptions) - - const activity = { - type: 'activity', - timestamp: '2020-05-27T15:13:30Z', - platform: PlatformType.GITHUB, - attributes: { - replies: 12, - body: 'Here', - }, - sentiment: { - positive: 0.98, - negative: 0.0, - neutral: 0.02, - mixed: 0.0, - label: 'positive', - sentiment: 0.98, - }, - isContribution: true, - username: 'anil', - member: returnedMember2.id, - score: 1, - sourceId: '#sourceId1', - } - - let activityCreated = await ActivityRepository.create(activity, mockIRepositoryOptions) - - // toMerge[1] = [(1,2),(1,4)] toMerge[2] = [(2,1)] toMerge[4] = [(4,1)] - // noMerge[2] = [3] - await MemberRepository.addToMerge( - [{ members: [returnedMember1.id, returnedMember2.id], similarity: null }], - mockIRepositoryOptions, - ) - await MemberRepository.addToMerge( - [{ members: [returnedMember1.id, returnedMember4.id], similarity: null }], - mockIRepositoryOptions, - ) - await MemberRepository.addToMerge( - [{ members: [returnedMember2.id, returnedMember1.id], similarity: null }], - mockIRepositoryOptions, - ) - await MemberRepository.addToMerge( - [{ members: [returnedMember4.id, returnedMember1.id], similarity: null }], - mockIRepositoryOptions, - ) - - await MemberRepository.addNoMerge( - returnedMember2.id, - returnedMember3.id, - mockIRepositoryOptions, - ) - - const response = await memberService.merge(returnedMember1.id, returnedMember2.id) - - const mergedMember = await MemberRepository.findById( - response.mergedId, - mockIRepositoryOptions, - ) - - // Sequelize returns associations as array of models, we need to get plain objects - mergedMember.tags = mergedMember.tags.map((i) => i.get({ plain: true })) - mergedMember.organizations = mergedMember.organizations.map((i) => - SequelizeTestUtils.objectWithoutKey(i.get({ plain: true }), ['memberOrganizations']), - ) - mergedMember.tasks = mergedMember.tasks.map((i) => i.get({ plain: true })) - mergedMember.notes = mergedMember.notes.map((i) => i.get({ plain: true })) - - // get the created activity again, it's member should be updated after merge - activityCreated = await ActivityRepository.findById( - activityCreated.id, - mockIRepositoryOptions, - ) - - // we don't need activity.member because we're already expecting member->activities - activityCreated = SequelizeTestUtils.objectWithoutKey(activityCreated, [ - 'member', - 'objectMember', - 'parent', - 'tasks', - 'display', - 'organization', - ]) - - // get previously created tags - t1 = await TagRepository.findById(t1.id, mockIRepositoryOptions) - t2 = await TagRepository.findById(t2.id, mockIRepositoryOptions) - t3 = await TagRepository.findById(t3.id, mockIRepositoryOptions) - - // get previously created organizations - o1 = await OrganizationRepository.findById(o1.id, mockIRepositoryOptions) - o2 = await OrganizationRepository.findById(o2.id, mockIRepositoryOptions) - o3 = await OrganizationRepository.findById(o3.id, mockIRepositoryOptions) - - // get previously created tasks - task1 = await TaskRepository.findById(task1.id, mockIRepositoryOptions) - task2 = await TaskRepository.findById(task2.id, mockIRepositoryOptions) - task3 = await TaskRepository.findById(task3.id, mockIRepositoryOptions) - - // get previously created notes - note1 = await NoteRepository.findById(note1.id, mockIRepositoryOptions) - note2 = await NoteRepository.findById(note2.id, mockIRepositoryOptions) - note3 = await NoteRepository.findById(note3.id, mockIRepositoryOptions) - - // remove tags->member relations as well (we should be only checking 1-deep relations) - t1 = SequelizeTestUtils.objectWithoutKey(t1, 'members') - t2 = SequelizeTestUtils.objectWithoutKey(t2, 'members') - t3 = SequelizeTestUtils.objectWithoutKey(t3, 'members') - - // remove organizations->member relations as well (we should be only checking 1-deep relations) - o1 = SequelizeTestUtils.objectWithoutKey(o1, [ - 'memberCount', - 'joinedAt', - 'activityCount', - 'memberOrganizations', - ]) - o2 = SequelizeTestUtils.objectWithoutKey(o2, [ - 'memberCount', - 'joinedAt', - 'activityCount', - 'memberOrganizations', - ]) - o3 = SequelizeTestUtils.objectWithoutKey(o3, [ - 'memberCount', - 'joinedAt', - 'activityCount', - 'memberOrganizations', - ]) - - // remove tasks->member and tasks->activity tasks->assignees relations as well (we should be only checking 1-deep relations) - task1 = SequelizeTestUtils.objectWithoutKey(task1, ['members', 'activities', 'assignees']) - task2 = SequelizeTestUtils.objectWithoutKey(task2, ['members', 'activities', 'assignees']) - task3 = SequelizeTestUtils.objectWithoutKey(task3, ['members', 'activities', 'assignees']) - - // remove notes->member relations as well (we should be only checking 1-deep relations) - note1 = SequelizeTestUtils.objectWithoutKey(note1, ['members', 'createdBy']) - note2 = SequelizeTestUtils.objectWithoutKey(note2, ['members', 'createdBy']) - note3 = SequelizeTestUtils.objectWithoutKey(note3, ['members', 'createdBy']) - - mergedMember.updatedAt = mergedMember.updatedAt.toISOString().split('T')[0] - - const expectedMember = { - id: returnedMember1.id, - username: { - [PlatformType.GITHUB]: ['anil'], - [PlatformType.DISCORD]: ['anil'], - }, - lastEnriched: null, - enrichedBy: [], - contributions: null, - displayName: 'Anil', - identities: [PlatformType.GITHUB, PlatformType.DISCORD], - attributes: { - ...member1.attributes, - ...member2.attributes, - }, - activeOn: [activityCreated.platform], - activityTypes: [`${activityCreated.platform}:${activityCreated.type}`], - emails: ['anil+1@crowd.dev', 'anil+2@crowd.dev', 'anil+3@crowd.dev'], - score: -1, - importHash: null, - createdAt: returnedMember1.createdAt, - updatedAt: SequelizeTestUtils.getNowWithoutTime(), - deletedAt: null, - tenantId: mockIRepositoryOptions.currentTenant.id, - segments: mockIRepositoryOptions.currentSegments, - createdById: mockIRepositoryOptions.currentUser.id, - updatedById: mockIRepositoryOptions.currentUser.id, - joinedAt: new Date(member1.joinedAt), - reach: { total: -1 }, - tags: [t1, t2, t3], - tasks: [task1, task2, task3], - notes: [note1, note2, note3], - organizations: [ - SequelizeTestUtils.objectWithoutKey(o1, [ - 'activeOn', - 'identities', - 'lastActive', - 'segments', - 'weakIdentities', - ]), - SequelizeTestUtils.objectWithoutKey(o2, [ - 'activeOn', - 'identities', - 'lastActive', - 'segments', - 'weakIdentities', - ]), - SequelizeTestUtils.objectWithoutKey(o3, [ - 'activeOn', - 'identities', - 'lastActive', - 'segments', - 'weakIdentities', - ]), - ], - noMerge: [returnedMember3.id], - toMerge: [returnedMember4.id], - activityCount: 1, - activeDaysCount: 1, - averageSentiment: activityCreated.sentiment.sentiment, - lastActive: activityCreated.timestamp, - lastActivity: activityCreated, - numberOfOpenSourceContributions: 0, - affiliations: [], - manuallyCreated: false, - } - - expect( - mergedMember.tasks.sort((a, b) => { - const nameA = a.name.toLowerCase() - const nameB = b.name.toLowerCase() - if (nameA < nameB) { - return -1 - } - if (nameA > nameB) { - return 1 - } - return 0 - }), - ).toEqual( - expectedMember.tasks.sort((a, b) => { - const nameA = a.name.toLowerCase() - const nameB = b.name.toLowerCase() - if (nameA < nameB) { - return -1 - } - if (nameA > nameB) { - return 1 - } - return 0 - }), - ) - - expect( - mergedMember.organizations.sort((a, b) => { - const nameA = a.displayName.toLowerCase() - const nameB = b.displayName.toLowerCase() - if (nameA < nameB) { - return -1 - } - if (nameA > nameB) { - return 1 - } - return 0 - }), - ).toEqual( - expectedMember.organizations.sort((a, b) => { - const nameA = a.displayName.toLowerCase() - const nameB = b.displayName.toLowerCase() - if (nameA < nameB) { - return -1 - } - if (nameA > nameB) { - return 1 - } - return 0 - }), - ) - delete mergedMember.tasks - delete expectedMember.tasks - delete mergedMember.organizations - delete expectedMember.organizations - - expect(mergedMember).toStrictEqual(expectedMember) - }) - - it('Should catch when two members are the same', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - const mas = new MemberAttributeSettingsService(mockIRepositoryOptions) - - await mas.createPredefined(GITHUB_MEMBER_ATTRIBUTES) - - const memberService = new MemberService(mockIRepositoryOptions) - - const member1 = { - username: { - [PlatformType.GITHUB]: 'anil', - }, - displayName: 'Anil', - joinedAt: '2021-05-27T15:14:30Z', - attributes: {}, - } - - const memberCreated = await MemberRepository.create(member1, mockIRepositoryOptions) - const mergeOutput = await memberService.merge(memberCreated.id, memberCreated.id) - - expect(mergeOutput).toStrictEqual({ status: 203, mergedId: memberCreated.id }) - - const found = await memberService.findById(memberCreated.id) - expect(found).toStrictEqual(memberCreated) - }) - }) - - describe('addToNoMerge method', () => { - it('Should add two members to their respective noMerges, these members should be excluded from toMerges respectively', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - const mas = new MemberAttributeSettingsService(mockIRepositoryOptions) - - await mas.createPredefined(GITHUB_MEMBER_ATTRIBUTES) - await mas.createPredefined(TWITTER_MEMBER_ATTRIBUTES) - await mas.createPredefined(DISCORD_MEMBER_ATTRIBUTES) - - const memberService = new MemberService(mockIRepositoryOptions) - - const member1 = { - username: { - [PlatformType.GITHUB]: 'anil', - }, - displayName: 'Anil', - joinedAt: '2021-05-27T15:14:30Z', - attributes: {}, - } - - const member2 = { - username: { - [PlatformType.DISCORD]: 'anil', - }, - displayName: 'Anil', - joinedAt: '2021-05-30T15:14:30Z', - attributes: { - [MemberAttributeName.SOURCE_ID]: { - [PlatformType.DISCORD]: '#discordId', - default: '#discordId', - }, - }, - } - - const member3 = { - username: { - [PlatformType.TWITTER]: 'anil', - }, - displayName: 'Anil', - joinedAt: '2021-05-30T15:14:30Z', - attributes: { - [MemberAttributeName.URL]: { - [PlatformType.TWITTER]: 'https://a-twitter-url', - default: 'https://a-twitter-url', - }, - }, - } - - let returnedMember1 = await MemberRepository.create(member1, mockIRepositoryOptions) - let returnedMember2 = await MemberRepository.create(member2, mockIRepositoryOptions) - let returnedMember3 = await MemberRepository.create(member3, mockIRepositoryOptions) - - // toMerge[1] = [(1,2),(1,3)] toMerge[2] = [(2,1),(2,3)] toMerge[3] = [(3,1),(3,2)] - await MemberRepository.addToMerge( - [{ members: [returnedMember1.id, returnedMember2.id], similarity: null }], - mockIRepositoryOptions, - ) - await MemberRepository.addToMerge( - [{ members: [returnedMember2.id, returnedMember1.id], similarity: null }], - mockIRepositoryOptions, - ) - - await MemberRepository.addToMerge( - [{ members: [returnedMember1.id, returnedMember3.id], similarity: null }], - mockIRepositoryOptions, - ) - await MemberRepository.addToMerge( - [{ members: [returnedMember3.id, returnedMember1.id], similarity: null }], - mockIRepositoryOptions, - ) - await MemberRepository.addToMerge( - [{ members: [returnedMember2.id, returnedMember3.id], similarity: null }], - mockIRepositoryOptions, - ) - await MemberRepository.addToMerge( - [{ members: [returnedMember3.id, returnedMember2.id], similarity: null }], - mockIRepositoryOptions, - ) - - await memberService.addToNoMerge(returnedMember1.id, returnedMember2.id) - - returnedMember1 = await MemberRepository.findById(returnedMember1.id, mockIRepositoryOptions) - - expect(returnedMember1.toMerge).toStrictEqual([returnedMember3.id]) - expect(returnedMember1.noMerge).toStrictEqual([returnedMember2.id]) - - returnedMember2 = await MemberRepository.findById(returnedMember2.id, mockIRepositoryOptions) - - expect(returnedMember2.toMerge).toStrictEqual([returnedMember3.id]) - expect(returnedMember2.noMerge).toStrictEqual([returnedMember1.id]) - - // call addToNoMerge once more, between member1 and member3 - await memberService.addToNoMerge(returnedMember1.id, returnedMember3.id) - - returnedMember1 = await MemberRepository.findById(returnedMember1.id, mockIRepositoryOptions) - - expect(returnedMember1.toMerge).toStrictEqual([]) - expect(returnedMember1.noMerge).toStrictEqual([returnedMember2.id, returnedMember3.id]) - - returnedMember3 = await MemberRepository.findById(returnedMember3.id, mockIRepositoryOptions) - - expect(returnedMember3.toMerge).toStrictEqual([returnedMember2.id]) - expect(returnedMember3.noMerge).toStrictEqual([returnedMember1.id]) - - // only toMerge relation (2,3) left. Testing addToNoMerge(2,3) - await memberService.addToNoMerge(returnedMember3.id, returnedMember2.id) - - returnedMember2 = await MemberRepository.findById(returnedMember2.id, mockIRepositoryOptions) - - expect(returnedMember2.toMerge).toStrictEqual([]) - expect(returnedMember2.noMerge).toStrictEqual([returnedMember1.id, returnedMember3.id]) - - returnedMember3 = await MemberRepository.findById(returnedMember3.id, mockIRepositoryOptions) - - expect(returnedMember3.toMerge).toStrictEqual([]) - expect(returnedMember3.noMerge).toStrictEqual([returnedMember1.id, returnedMember2.id]) - }) - - it('Should throw 404 not found when trying to add non existent members to noMerge', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - const mas = new MemberAttributeSettingsService(mockIRepositoryOptions) - - await mas.createPredefined(GITHUB_MEMBER_ATTRIBUTES) - - const memberService = new MemberService(mockIRepositoryOptions) - - const member1 = { - username: { - [PlatformType.GITHUB]: 'anil', - }, - displayName: 'Anil', - joinedAt: '2021-05-27T15:14:30Z', - attributes: {}, - } - - const returnedMember1 = await MemberRepository.create(member1, mockIRepositoryOptions) - - const { randomUUID } = require('crypto') - - await expect(() => - memberService.addToNoMerge(returnedMember1.id, randomUUID()), - ).rejects.toThrowError(new Error404()) - }) - }) - - describe('memberExists method', () => { - it('Should find existing member with string username and default platform', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - const mas = new MemberAttributeSettingsService(mockIRepositoryOptions) - - await mas.createPredefined(GITHUB_MEMBER_ATTRIBUTES) - - const memberService = new MemberService(mockIRepositoryOptions) - - const member1 = { - username: { - [PlatformType.GITHUB]: 'anil', - }, - displayName: 'Anil', - joinedAt: '2021-05-27T15:14:30Z', - attributes: {}, - } - - const cloned = lodash.cloneDeep(member1) - const returnedMember1 = await MemberRepository.create(cloned, mockIRepositoryOptions) - delete returnedMember1.toMerge - delete returnedMember1.noMerge - delete returnedMember1.tags - delete returnedMember1.activities - delete returnedMember1.tasks - delete returnedMember1.notes - delete returnedMember1.activityCount - delete returnedMember1.averageSentiment - delete returnedMember1.lastActive - delete returnedMember1.lastActivity - delete returnedMember1.activeOn - delete returnedMember1.identities - delete returnedMember1.activityTypes - delete returnedMember1.activeDaysCount - delete returnedMember1.numberOfOpenSourceContributions - delete returnedMember1.affiliations - delete returnedMember1.manuallyCreated - - returnedMember1.segments = returnedMember1.segments.map((s) => s.id) - - const existing = await memberService.memberExists( - member1.username[PlatformType.GITHUB], - PlatformType.GITHUB, - ) - - expect(existing).toStrictEqual(returnedMember1) - }) - - it('Should return null if member is not found - string type', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - const mas = new MemberAttributeSettingsService(mockIRepositoryOptions) - - await mas.createPredefined(GITHUB_MEMBER_ATTRIBUTES) - - const memberService = new MemberService(mockIRepositoryOptions) - - const member1 = { - username: { - [PlatformType.GITHUB]: 'anil', - }, - displayName: 'Anil', - joinedAt: '2021-05-27T15:14:30Z', - attributes: {}, - } - - await MemberRepository.create(member1, mockIRepositoryOptions) - - const existing = await memberService.memberExists('some-random-username', PlatformType.GITHUB) - - expect(existing).toBeNull() - }) - - it('Should return null if member is not found - object type', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - const mas = new MemberAttributeSettingsService(mockIRepositoryOptions) - - await mas.createPredefined(GITHUB_MEMBER_ATTRIBUTES) - - const memberService = new MemberService(mockIRepositoryOptions) - - const member1 = { - username: { - [PlatformType.GITHUB]: 'anil', - }, - displayName: 'Anil', - joinedAt: '2021-05-27T15:14:30Z', - attributes: {}, - } - - await MemberRepository.create(member1, mockIRepositoryOptions) - - const existing = await memberService.memberExists( - { - ...member1.username, - [PlatformType.SLACK]: 'some-slack-username', - }, - PlatformType.SLACK, - ) - - expect(existing).toBeNull() - }) - - it('Should find existing member with object username and given platform', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - const mas = new MemberAttributeSettingsService(mockIRepositoryOptions) - - await mas.createPredefined(GITHUB_MEMBER_ATTRIBUTES) - - const memberService = new MemberService(mockIRepositoryOptions) - - const member1 = { - username: { - [PlatformType.GITHUB]: 'anil', - [PlatformType.DISCORD]: 'some-other-username', - }, - displayName: 'Anil', - joinedAt: '2021-05-27T15:14:30Z', - attributes: {}, - } - - const returnedMember1 = await MemberRepository.create(member1, mockIRepositoryOptions) - delete returnedMember1.toMerge - delete returnedMember1.noMerge - delete returnedMember1.tags - delete returnedMember1.activities - delete returnedMember1.tasks - delete returnedMember1.notes - delete returnedMember1.activityCount - delete returnedMember1.averageSentiment - delete returnedMember1.lastActive - delete returnedMember1.lastActivity - delete returnedMember1.activeOn - delete returnedMember1.identities - delete returnedMember1.activityTypes - delete returnedMember1.activeDaysCount - delete returnedMember1.numberOfOpenSourceContributions - delete returnedMember1.affiliations - delete returnedMember1.manuallyCreated - - returnedMember1.segments = returnedMember1.segments.map((s) => s.id) - - const existing = await memberService.memberExists( - { [PlatformType.DISCORD]: 'some-other-username' }, - PlatformType.DISCORD, - ) - - expect(returnedMember1).toStrictEqual(existing) - }) - - it('Should throw 400 error when username is type of object and username[platform] is not present ', async () => { - const mockIRepositoryOptions = await SequelizeTestUtils.getTestIRepositoryOptions(db) - const mas = new MemberAttributeSettingsService(mockIRepositoryOptions) - - await mas.createPredefined(GITHUB_MEMBER_ATTRIBUTES) - - const memberService = new MemberService(mockIRepositoryOptions) - - const member1 = { - username: { - [PlatformType.GITHUB]: 'anil', - [PlatformType.DISCORD]: 'some-other-username', - }, - displayName: 'Anil', - joinedAt: '2021-05-27T15:14:30Z', - attributes: {}, - } - - await MemberRepository.create(member1, mockIRepositoryOptions) - - await expect(() => - memberService.memberExists( - { [PlatformType.DISCORD]: 'some-other-username' }, - PlatformType.SLACK, - ), - ).rejects.toThrowError(new Error400()) - }) - }) - - describe('Update Reach method', () => { - it('Should keep as total: -1 for an empty new reach and a default old reach', async () => { - const oldReach = { total: -1 } - const updatedReach = MemberService.calculateReach({}, oldReach) - expect(updatedReach).toStrictEqual({ - total: -1, - }) - }) - it('Should keep as total: -1 for a default new reach and a default old reach', async () => { - const oldReach = { total: -1 } - const updatedReach = MemberService.calculateReach({ total: -1 }, oldReach) - expect(updatedReach).toStrictEqual({ - total: -1, - }) - }) - it('Should update for a new reach and a default old reach', async () => { - const oldReach = { total: -1 } - const newReach = { [PlatformType.TWITTER]: 10 } - const updatedReach = MemberService.calculateReach(oldReach, newReach) - expect(updatedReach).toStrictEqual({ - total: 10, - [PlatformType.TWITTER]: 10, - }) - }) - it('Should update for a new reach and old reach in the same platform', async () => { - const oldReach = { [PlatformType.TWITTER]: 5, total: 5 } - const newReach = { [PlatformType.TWITTER]: 10 } - const updatedReach = MemberService.calculateReach(oldReach, newReach) - expect(updatedReach).toStrictEqual({ - total: 10, - [PlatformType.TWITTER]: 10, - }) - }) - it('Should update for a complex reach with different platforms', async () => { - const oldReach = { - [PlatformType.TWITTER]: 10, - [PlatformType.GITHUB]: 20, - [PlatformType.DISCORD]: 50, - total: 10 + 20 + 50, - } - const newReach = { - [PlatformType.TWITTER]: 20, - [PlatformType.GITHUB]: 2, - linkedin: 10, - total: 20 + 2 + 10, - } - const updatedReach = MemberService.calculateReach(oldReach, newReach) - expect(updatedReach).toStrictEqual({ - total: 10 + 20 + 2 + 50, - [PlatformType.TWITTER]: 20, - [PlatformType.GITHUB]: 2, - linkedin: 10, - [PlatformType.DISCORD]: 50, - }) - }) - it('Should work with reach 0', async () => { - const oldReach = { total: -1 } - const newReach = { [PlatformType.TWITTER]: 0 } - const updatedReach = MemberService.calculateReach(oldReach, newReach) - expect(updatedReach).toStrictEqual({ - total: 0, - [PlatformType.TWITTER]: 0, - }) - }) - }) - - describe('getHighestPriorityPlatformForAttributes method', () => { - it('Should return the highest priority platform from a priority array, handling the exceptions', async () => { - const priorityArray = [ - PlatformType.TWITTER, - PlatformType.CROWD, - PlatformType.SLACK, - PlatformType.DEVTO, - PlatformType.DISCORD, - PlatformType.GITHUB, - ] - - let inputPlatforms = [PlatformType.GITHUB, PlatformType.DEVTO] - let highestPriorityPlatform = MemberService.getHighestPriorityPlatformForAttributes( - inputPlatforms, - priorityArray, - ) - - expect(highestPriorityPlatform).toBe(PlatformType.DEVTO) - - inputPlatforms = [PlatformType.GITHUB, 'someOtherPlatform'] as any - highestPriorityPlatform = MemberService.getHighestPriorityPlatformForAttributes( - inputPlatforms, - priorityArray, - ) - - expect(highestPriorityPlatform).toBe(PlatformType.GITHUB) - - inputPlatforms = ['somePlatform1', 'somePlatform2'] as any - - // if no match in the priority array, it should return the first platform it finds - highestPriorityPlatform = MemberService.getHighestPriorityPlatformForAttributes( - inputPlatforms, - priorityArray, - ) - - expect(highestPriorityPlatform).toBe('somePlatform1') - - inputPlatforms = [] - - // if no platforms are sent to choose from, it should return undefined - highestPriorityPlatform = MemberService.getHighestPriorityPlatformForAttributes( - inputPlatforms, - priorityArray, - ) - expect(highestPriorityPlatform).not.toBeDefined() - }) - }) - - describe('validateAttributes method', () => { - it('Should validate attributes object succesfully', async () => { - const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db) - - const memberService = new MemberService(mockIServiceOptions) - const memberAttributeSettingsService = new MemberAttributeSettingsService(mockIServiceOptions) - - await memberAttributeSettingsService.createPredefined(GITHUB_MEMBER_ATTRIBUTES) - await memberAttributeSettingsService.createPredefined(TWITTER_MEMBER_ATTRIBUTES) - await memberAttributeSettingsService.createPredefined(DEVTO_MEMBER_ATTRIBUTES) - - const attributes = { - [MemberAttributeName.NAME]: { - [PlatformType.DEVTO]: 'Dweet Srute', - }, - [MemberAttributeName.URL]: { - [PlatformType.GITHUB]: 'https://some-github-url', - [PlatformType.TWITTER]: 'https://some-twitter-url', - [PlatformType.DEVTO]: 'https://some-devto-url', - }, - [MemberAttributeName.LOCATION]: { - [PlatformType.GITHUB]: 'Berlin', - [PlatformType.DEVTO]: 'Istanbul', - }, - [MemberAttributeName.BIO]: { - [PlatformType.GITHUB]: 'Assistant to the Regional Manager', - [PlatformType.DEVTO]: 'Assistant Regional Manager', - }, - [MemberAttributeName.AVATAR_URL]: { - [PlatformType.TWITTER]: 'https://some-image-url', - }, - } - - const validateAttributes = await memberService.validateAttributes(attributes) - - expect(validateAttributes).toEqual(attributes) - }) - - it(`Should accept custom attributes without 'custom' platform key`, async () => { - const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db) - - const memberService = new MemberService(mockIServiceOptions) - const memberAttributeSettingsService = new MemberAttributeSettingsService(mockIServiceOptions) - - await memberAttributeSettingsService.createPredefined(GITHUB_MEMBER_ATTRIBUTES) - - const attributes = { - [MemberAttributeName.BIO]: 'Assistant to the Regional Manager', - } - - const validateAttributes = await memberService.validateAttributes(attributes) - - const expectedValidatedAttributes = { - [MemberAttributeName.BIO]: { - custom: 'Assistant to the Regional Manager', - }, - } - - expect(validateAttributes).toEqual(expectedValidatedAttributes) - }) - - it(`Should accept custom attributes both without and with 'custom' platform key`, async () => { - const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db) - - const memberService = new MemberService(mockIServiceOptions) - const memberAttributeSettingsService = new MemberAttributeSettingsService(mockIServiceOptions) - - await memberAttributeSettingsService.createPredefined(GITHUB_MEMBER_ATTRIBUTES) - await memberAttributeSettingsService.createPredefined(TWITTER_MEMBER_ATTRIBUTES) - await memberAttributeSettingsService.createPredefined(DEVTO_MEMBER_ATTRIBUTES) - - const attributes = { - [MemberAttributeName.NAME]: 'Dwight Schrute', - [MemberAttributeName.URL]: 'https://some-url', - [MemberAttributeName.LOCATION]: { - [PlatformType.GITHUB]: 'Berlin', - [PlatformType.DEVTO]: 'Istanbul', - custom: 'a custom location', - }, - [MemberAttributeName.BIO]: { - [PlatformType.GITHUB]: 'Assistant to the Regional Manager', - [PlatformType.DEVTO]: 'Assistant Regional Manager', - custom: 'a custom bio', - }, - [MemberAttributeName.AVATAR_URL]: { - [PlatformType.TWITTER]: 'https://some-image-url', - custom: 'a custom image url', - }, - } - - const validateAttributes = await memberService.validateAttributes(attributes) - - const expectedValidatedAttributes = { - [MemberAttributeName.NAME]: { - custom: 'Dwight Schrute', - }, - [MemberAttributeName.URL]: { - custom: 'https://some-url', - }, - [MemberAttributeName.LOCATION]: { - [PlatformType.GITHUB]: 'Berlin', - [PlatformType.DEVTO]: 'Istanbul', - custom: 'a custom location', - }, - [MemberAttributeName.BIO]: { - [PlatformType.GITHUB]: 'Assistant to the Regional Manager', - [PlatformType.DEVTO]: 'Assistant Regional Manager', - custom: 'a custom bio', - }, - [MemberAttributeName.AVATAR_URL]: { - [PlatformType.TWITTER]: 'https://some-image-url', - custom: 'a custom image url', - }, - } - - expect(validateAttributes).toEqual(expectedValidatedAttributes) - }) - - it('Should throw a 400 Error when an attribute does not exist in member attribute settings', async () => { - const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db) - - const memberService = new MemberService(mockIServiceOptions) - const memberAttributeSettingsService = new MemberAttributeSettingsService(mockIServiceOptions) - - await memberAttributeSettingsService.createPredefined(GITHUB_MEMBER_ATTRIBUTES) - await memberAttributeSettingsService.createPredefined(TWITTER_MEMBER_ATTRIBUTES) - - // in settings name has a string type, inserting an integer should throw an error - const attributes = { - [MemberAttributeName.URL]: { - [PlatformType.GITHUB]: 'https://some-github-url', - }, - [MemberAttributeName.AVATAR_URL]: { - [PlatformType.TWITTER]: 'https://some-image-url', - }, - 'non-existing-attribute': { - [PlatformType.TWITTER]: 'some value', - }, - } - const validateAttributes = await memberService.validateAttributes(attributes) - - // member attribute that is non existing in settings, should be omitted after validate - const expectedValidatedAttributes = { - [MemberAttributeName.URL]: { - [PlatformType.GITHUB]: 'https://some-github-url', - }, - [MemberAttributeName.AVATAR_URL]: { - [PlatformType.TWITTER]: 'https://some-image-url', - }, - } - expect(validateAttributes).toEqual(expectedValidatedAttributes) - }) - - it('Should throw a 400 Error when the type of an attribute does not match the type in member attribute settings', async () => { - const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db) - - const memberService = new MemberService(mockIServiceOptions) - const memberAttributeSettingsService = new MemberAttributeSettingsService(mockIServiceOptions) - - await memberAttributeSettingsService.createPredefined(GITHUB_MEMBER_ATTRIBUTES) - await memberAttributeSettingsService.createPredefined(TWITTER_MEMBER_ATTRIBUTES) - - // in settings website_url has a url type, inserting an integer should throw an error - const attributes = { - [MemberAttributeName.WEBSITE_URL]: { - [PlatformType.GITHUB]: 55, - }, - [MemberAttributeName.URL]: { - [PlatformType.GITHUB]: 'https://some-github-url', - [PlatformType.TWITTER]: 'https://some-twitter-url', - }, - [MemberAttributeName.AVATAR_URL]: { - [PlatformType.TWITTER]: 'https://some-image-url', - }, - } - - await expect(() => memberService.validateAttributes(attributes)).rejects.toThrowError( - new Error400('en', 'settings.memberAttributes.wrongType'), - ) - }) - }) - describe('setAttributesDefaultValues method', () => { - it('Should return the structured attributes object with default values succesfully', async () => { - const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db) - - const memberService = new MemberService(mockIServiceOptions) - const memberAttributeSettingsService = new MemberAttributeSettingsService(mockIServiceOptions) - - await memberAttributeSettingsService.createPredefined(GITHUB_MEMBER_ATTRIBUTES) - await memberAttributeSettingsService.createPredefined(TWITTER_MEMBER_ATTRIBUTES) - await memberAttributeSettingsService.createPredefined(DEVTO_MEMBER_ATTRIBUTES) - - const attributes = { - [MemberAttributeName.NAME]: { - [PlatformType.DEVTO]: 'Dweet Srute', - }, - [MemberAttributeName.URL]: { - [PlatformType.GITHUB]: 'https://some-github-url', - [PlatformType.TWITTER]: 'https://some-twitter-url', - [PlatformType.DEVTO]: 'https://some-devto-url', - }, - [MemberAttributeName.LOCATION]: { - [PlatformType.GITHUB]: 'Berlin', - [PlatformType.DEVTO]: 'Istanbul', - }, - [MemberAttributeName.BIO]: { - [PlatformType.GITHUB]: 'Assistant to the Regional Manager', - [PlatformType.DEVTO]: 'Assistant Regional Manager', - }, - [MemberAttributeName.AVATAR_URL]: { - [PlatformType.TWITTER]: 'https://some-image-url', - }, - } - - const attributesWithDefaultValues = await memberService.setAttributesDefaultValues(attributes) - - // Default platform priority is: custom, twitter, github, devto, slack, discord, crowd - const expectedAttributesWithDefaultValues = { - [MemberAttributeName.URL]: { - [PlatformType.GITHUB]: attributes[MemberAttributeName.URL][PlatformType.GITHUB], - [PlatformType.TWITTER]: attributes[MemberAttributeName.URL][PlatformType.TWITTER], - [PlatformType.DEVTO]: attributes[MemberAttributeName.URL][PlatformType.DEVTO], - default: attributes[MemberAttributeName.URL][PlatformType.TWITTER], - }, - [MemberAttributeName.NAME]: { - [PlatformType.DEVTO]: attributes[MemberAttributeName.NAME][PlatformType.DEVTO], - default: attributes[MemberAttributeName.NAME][PlatformType.DEVTO], - }, - [MemberAttributeName.AVATAR_URL]: { - [PlatformType.TWITTER]: attributes[MemberAttributeName.AVATAR_URL][PlatformType.TWITTER], - default: attributes[MemberAttributeName.AVATAR_URL][PlatformType.TWITTER], - }, - [MemberAttributeName.BIO]: { - [PlatformType.GITHUB]: attributes[MemberAttributeName.BIO][PlatformType.GITHUB], - [PlatformType.DEVTO]: attributes[MemberAttributeName.BIO][PlatformType.DEVTO], - default: attributes[MemberAttributeName.BIO][PlatformType.GITHUB], - }, - [MemberAttributeName.LOCATION]: { - [PlatformType.GITHUB]: attributes[MemberAttributeName.LOCATION][PlatformType.GITHUB], - [PlatformType.DEVTO]: attributes[MemberAttributeName.LOCATION][PlatformType.DEVTO], - default: attributes[MemberAttributeName.LOCATION][PlatformType.GITHUB], - }, - } - - expect(attributesWithDefaultValues).toEqual(expectedAttributesWithDefaultValues) - }) - - it('Should throw a 400 Error when priority array does not exist', async () => { - const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db) - - const memberService = new MemberService(mockIServiceOptions) - const memberAttributeSettingsService = new MemberAttributeSettingsService(mockIServiceOptions) - - await memberAttributeSettingsService.createPredefined(GITHUB_MEMBER_ATTRIBUTES) - await memberAttributeSettingsService.createPredefined(TWITTER_MEMBER_ATTRIBUTES) - await memberAttributeSettingsService.createPredefined(DEVTO_MEMBER_ATTRIBUTES) - - // Empty default priority array - const settings = await SettingsRepository.findOrCreateDefault({}, mockIServiceOptions) - - await SettingsRepository.save( - { ...settings, attributeSettings: { priorities: [] } }, - mockIServiceOptions, - ) - const attributes = { - [MemberAttributeName.NAME]: { - [PlatformType.DEVTO]: 'Dweet Srute', - }, - [MemberAttributeName.URL]: { - [PlatformType.GITHUB]: 'https://some-github-url', - [PlatformType.TWITTER]: 'https://some-twitter-url', - [PlatformType.DEVTO]: 'https://some-devto-url', - }, - [MemberAttributeName.LOCATION]: { - [PlatformType.GITHUB]: 'Berlin', - [PlatformType.DEVTO]: 'Istanbul', - }, - [MemberAttributeName.BIO]: { - [PlatformType.GITHUB]: 'Assistant to the Regional Manager', - [PlatformType.DEVTO]: 'Assistant Regional Manager', - }, - [MemberAttributeName.AVATAR_URL]: { - [PlatformType.TWITTER]: 'https://some-image-url', - }, - } - - await expect(() => memberService.setAttributesDefaultValues(attributes)).rejects.toThrowError( - new Error400('en', 'settings.memberAttributes.priorityArrayNotFound'), - ) - }) - }) - - describe('findAndCountAll method', () => { - it('Should filter and sort by dynamic attributes using advanced filters successfully', async () => { - const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db) - - const ms = new MemberService(mockIServiceOptions) - - const mas = new MemberAttributeSettingsService(mockIServiceOptions) - - await mas.createPredefined(GITHUB_MEMBER_ATTRIBUTES) - await mas.createPredefined(TWITTER_MEMBER_ATTRIBUTES) - await mas.createPredefined(DISCORD_MEMBER_ATTRIBUTES) - - const attribute1 = { - name: 'aNumberAttribute', - label: 'A number Attribute', - type: MemberAttributeType.NUMBER, - canDelete: true, - show: true, - } - - const attribute2 = { - name: 'aDateAttribute', - label: 'A date Attribute', - type: MemberAttributeType.DATE, - canDelete: true, - show: true, - } - - const attribute3 = { - name: 'aMultiSelectAttribute', - label: 'A multi select Attribute', - options: ['a', 'b', 'c'], - type: MemberAttributeType.MULTI_SELECT, - canDelete: true, - show: true, - } - - await mas.create(attribute1) - await mas.create(attribute2) - await mas.create(attribute3) - - const member1 = { - username: { - [PlatformType.GITHUB]: 'anil', - [PlatformType.DISCORD]: 'anil', - [PlatformType.TWITTER]: 'anil', - }, - platform: PlatformType.GITHUB, - emails: ['lala@l.com'], - score: 10, - attributes: { - aDateAttribute: { - custom: '2022-08-01T00:00:00', - }, - aMultiSelectAttribute: { - custom: ['a', 'b'], - github: ['a'], - }, - [MemberAttributeName.IS_HIREABLE]: { - [PlatformType.GITHUB]: false, - [PlatformType.DISCORD]: true, - }, - [MemberAttributeName.URL]: { - [PlatformType.GITHUB]: 'https://github.com/anil', - [PlatformType.TWITTER]: 'https://twitter.com/anil', - }, - [MemberAttributeName.WEBSITE_URL]: { - [PlatformType.GITHUB]: 'https://imcvampire.js.org/', - }, - [MemberAttributeName.BIO]: { - [PlatformType.GITHUB]: 'Lazy geek', - }, - [MemberAttributeName.LOCATION]: { - [PlatformType.GITHUB]: 'Helsinki, Finland', - }, - [MemberAttributeName.SOURCE_ID]: { - [PlatformType.TWITTER]: '#twitterId2', - [PlatformType.DISCORD]: '#discordId1', - }, - [MemberAttributeName.AVATAR_URL]: { - [PlatformType.TWITTER]: 'https://twitter.com/anil/image', - }, - aNumberAttribute: { - [PlatformType.GITHUB]: 1, - [PlatformType.TWITTER]: 2, - [PlatformType.DISCORD]: 300000, - }, - }, - contributions: [ - { - id: 112529473, - url: 'https://github.com/bighead/silicon-valley', - topics: ['TV Shows', 'Comedy', 'Startups'], - summary: 'Silicon Valley: 50 commits in 2 weeks', - numberCommits: 50, - lastCommitDate: '02/01/2023', - firstCommitDate: '01/17/2023', - }, - { - id: 112529474, - url: 'https://github.com/bighead/startup-ideas', - topics: ['Ideas', 'Startups'], - summary: 'Startup Ideas: 20 commits in 1 week', - numberCommits: 20, - lastCommitDate: '03/01/2023', - firstCommitDate: '02/22/2023', - }, - ], - joinedAt: '2022-05-28T15:13:30', - } - - const member2 = { - username: { - [PlatformType.GITHUB]: 'michaelScott', - [PlatformType.DISCORD]: 'michaelScott', - [PlatformType.TWITTER]: 'michaelScott', - }, - platform: PlatformType.GITHUB, - emails: ['michael@mifflin.com'], - score: 10, - attributes: { - aDateAttribute: { - custom: '2022-08-06T00:00:00', - }, - aMultiSelectAttribute: { - custom: ['b', 'c'], - github: ['b'], - }, - [MemberAttributeName.IS_HIREABLE]: { - [PlatformType.GITHUB]: true, - [PlatformType.DISCORD]: true, - }, - [MemberAttributeName.URL]: { - [PlatformType.GITHUB]: 'https://github.com/michael-scott', - [PlatformType.TWITTER]: 'https://twitter.com/michael', - }, - [MemberAttributeName.WEBSITE_URL]: { - [PlatformType.GITHUB]: 'https://website/michael', - }, - [MemberAttributeName.BIO]: { - [PlatformType.GITHUB]: 'Dunder & Mifflin Regional Manager', - }, - [MemberAttributeName.LOCATION]: { - [PlatformType.GITHUB]: 'Berlin', - }, - [MemberAttributeName.SOURCE_ID]: { - [PlatformType.TWITTER]: '#twitterId2', - [PlatformType.DISCORD]: '#discordId2', - }, - [MemberAttributeName.AVATAR_URL]: { - [PlatformType.TWITTER]: 'https://twitter.com/michael/image', - }, - aNumberAttribute: { - [PlatformType.GITHUB]: 1500, - [PlatformType.TWITTER]: 2500, - [PlatformType.DISCORD]: 2, - }, - }, - contributions: [ - { - id: 112529472, - url: 'https://github.com/bachman/pied-piper', - topics: ['compression', 'data', 'middle-out', 'Java'], - summary: 'Pied Piper: 10 commits in 1 day', - numberCommits: 10, - lastCommitDate: '2023-03-10', - firstCommitDate: '2023-03-01', - }, - { - id: 112529473, - url: 'https://github.com/bachman/aviato', - topics: ['Python', 'Django'], - summary: 'Aviato: 5 commits in 1 day', - numberCommits: 5, - lastCommitDate: '2023-02-25', - firstCommitDate: '2023-02-20', - }, - { - id: 112529476, - url: 'https://github.com/bachman/erlichbot', - topics: ['Python', 'Slack API'], - summary: 'ErlichBot: 2 commits in 1 day', - numberCommits: 2, - lastCommitDate: '2023-01-25', - firstCommitDate: '2023-01-24', - }, - ], - joinedAt: '2022-09-15T15:13:30', - } - - const member3 = { - username: { - [PlatformType.GITHUB]: 'jimHalpert', - [PlatformType.DISCORD]: 'jimHalpert', - [PlatformType.TWITTER]: 'jimHalpert', - }, - platform: PlatformType.GITHUB, - emails: ['jim@mifflin.com'], - score: 10, - attributes: { - aDateAttribute: { - custom: '2022-08-15T00:00:00', - }, - aMultiSelectAttribute: { - custom: ['a', 'c'], - github: ['c'], - }, - [MemberAttributeName.IS_HIREABLE]: { - [PlatformType.GITHUB]: false, - [PlatformType.DISCORD]: true, - }, - [MemberAttributeName.URL]: { - [PlatformType.GITHUB]: 'https://github.com/jim-halpert', - [PlatformType.TWITTER]: 'https://twitter.com/jim', - }, - [MemberAttributeName.WEBSITE_URL]: { - [PlatformType.GITHUB]: 'https://website/jim', - }, - [MemberAttributeName.BIO]: { - [PlatformType.GITHUB]: 'Sales guy', - }, - [MemberAttributeName.LOCATION]: { - [PlatformType.GITHUB]: 'Scranton', - }, - [MemberAttributeName.SOURCE_ID]: { - [PlatformType.TWITTER]: '#twitterId3', - [PlatformType.DISCORD]: '#discordId3', - }, - [MemberAttributeName.AVATAR_URL]: { - [PlatformType.TWITTER]: 'https://twitter.com/jim/image', - }, - aNumberAttribute: { - [PlatformType.GITHUB]: 15500, - [PlatformType.TWITTER]: 25500, - [PlatformType.DISCORD]: 200000, - }, - }, - joinedAt: '2022-09-16T15:13:30Z', - } - - const member1Created = await ms.upsert(member1) - const member2Created = await ms.upsert(member2) - const member3Created = await ms.upsert(member3) - - await SequelizeTestUtils.refreshMaterializedViews(db) - - // filter and sort by aNumberAttribute default values - let members = await ms.findAndCountAll({ - advancedFilter: { - aNumberAttribute: { - gte: 1000, - }, - }, - orderBy: 'aNumberAttribute_DESC', - }) - - expect(members.count).toBe(2) - expect(members.rows.map((i) => i.id)).toStrictEqual([member3Created.id, member2Created.id]) - - // filter and sort by aNumberAttribute platform specific values - members = await ms.findAndCountAll({ - advancedFilter: { - 'attributes.aNumberAttribute.discord': { - gte: 100000, - }, - }, - orderBy: 'attributes.aNumberAttribute.discord_DESC', - }) - - expect(members.count).toBe(2) - expect(members.rows.map((i) => i.id)).toStrictEqual([member1Created.id, member3Created.id]) - - // filter by isHireable default values - members = await ms.findAndCountAll({ - advancedFilter: { - isHireable: true, - }, - }) - - expect(members.count).toBe(1) - expect(members.rows.map((i) => i.id)).toStrictEqual([member2Created.id]) - - // filter by isHireable platform specific values - members = await ms.findAndCountAll({ - advancedFilter: { - 'attributes.isHireable.discord': true, - }, - }) - - expect(members.count).toBe(3) - expect(members.rows.map((i) => i.id)).toStrictEqual([ - member3Created.id, - member2Created.id, - member1Created.id, - ]) - - // filter and sort by url default values - members = await ms.findAndCountAll({ - advancedFilter: { - url: { - textContains: 'jim', - }, - }, - orderBy: 'url_DESC', - }) - - expect(members.count).toBe(1) - expect(members.rows.map((i) => i.id)).toStrictEqual([member3Created.id]) - - // filter and sort by url platform specific values - members = await ms.findAndCountAll({ - advancedFilter: { - 'attributes.url.github': { - textContains: 'github', - }, - }, - orderBy: 'attributes.url.github_ASC', - }) - - expect(members.count).toBe(3) - - // results will be sorted by github.url anil -> jim -> michael - expect(members.rows.map((i) => i.id)).toStrictEqual([ - member1Created.id, - member3Created.id, - member2Created.id, - ]) - - // filter and sort by custom aDateAttribute - members = await ms.findAndCountAll({ - advancedFilter: { - aDateAttribute: { - lte: '2022-08-06T00:00:00', - }, - }, - orderBy: 'aDateAttribute_DESC', - }) - - expect(members.count).toBe(2) - expect(members.rows.map((i) => i.id)).toStrictEqual([member2Created.id, member1Created.id]) - - // filter by custom aMultiSelectAttribute - members = await ms.findAndCountAll({ - advancedFilter: { - aMultiSelectAttribute: { - overlap: ['a'], - }, - }, - orderBy: 'createdAt_DESC', - }) - expect(members.count).toBe(2) - expect(members.rows.map((i) => i.id)).toStrictEqual([member3Created.id, member1Created.id]) - - // filter by numberOfOpenSourceContributions - members = await ms.findAndCountAll({ - filter: { - numberOfOpenSourceContributionsRange: [2, 6], - }, - }) - expect(members.count).toBe(2) - expect(members.rows.map((i) => i.id)).toEqual([member2Created.id, member1Created.id]) - - // filter by numberOfOpenSourceContributions only start - members = await ms.findAndCountAll({ - filter: { - numberOfOpenSourceContributionsRange: [3], - }, - }) - expect(members.count).toBe(1) - expect(members.rows.map((i) => i.id)).toStrictEqual([member2Created.id]) - - // filter and sort by numberOfOpenSourceContributions - members = await ms.findAndCountAll({ - filter: { - numberOfOpenSourceContributionsRange: [2, 6], - }, - orderBy: 'numberOfOpenSourceContributions_ASC', - }) - expect(members.count).toBe(2) - expect(members.rows.map((i) => i.id)).toStrictEqual([member1Created.id, member2Created.id]) - - // sort by numberOfOpenSourceContributions - members = await ms.findAndCountAll({ - orderBy: 'numberOfOpenSourceContributions_ASC', - }) - expect(members.count).toBe(3) - expect(members.rows.map((i) => i.id)).toStrictEqual([ - member3Created.id, - member1Created.id, - member2Created.id, - ]) - }) - }) -}) diff --git a/backend/src/services/__tests__/organizationService.test.ts b/backend/src/services/__tests__/organizationService.test.ts index 5843e402e1..3920262563 100644 --- a/backend/src/services/__tests__/organizationService.test.ts +++ b/backend/src/services/__tests__/organizationService.test.ts @@ -1,6 +1,5 @@ -import organizationCacheRepository from '../../database/repositories/organizationCacheRepository' +import { TenantPlans } from '@crowd/types' import SequelizeTestUtils from '../../database/utils/sequelizeTestUtils' -import Plans from '../../security/plans' import OrganizationService from '../organizationService' const db = null @@ -19,7 +18,7 @@ describe('OrganizationService tests', () => { it('Should create organization', async () => { const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions( db, - Plans.values.growth, + TenantPlans.Growth, ) const service = new OrganizationService(mockIServiceOptions) @@ -39,7 +38,7 @@ describe('OrganizationService tests', () => { it('Should throw an error when name is not sent', async () => { const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions( db, - Plans.values.growth, + TenantPlans.Growth, ) const service = new OrganizationService(mockIServiceOptions) diff --git a/backend/src/services/__tests__/tenantService.test.ts b/backend/src/services/__tests__/tenantService.test.ts index c2cc9666d3..32f4119481 100644 --- a/backend/src/services/__tests__/tenantService.test.ts +++ b/backend/src/services/__tests__/tenantService.test.ts @@ -1,16 +1,14 @@ -import moment from 'moment' +import { generateUUIDv1 } from '@crowd/common' +import { getRedisClient } from '@crowd/redis' +import { MemberAttributeName, PlatformType } from '@crowd/types' +import { REDIS_CONFIG } from '../../conf' import SequelizeTestUtils from '../../database/utils/sequelizeTestUtils' -import TenantService from '../tenantService' -import MemberService from '../memberService' import { IServiceOptions } from '../IServiceOptions' -import MicroserviceService from '../microserviceService' -import { MemberAttributeName, PlatformType } from '@crowd/types' import MemberAttributeSettingsService from '../memberAttributeSettingsService' +import MemberService from '../memberService' +import MicroserviceService from '../microserviceService' import TaskService from '../taskService' -import Plans from '../../security/plans' -import { generateUUIDv1 } from '@crowd/common' -import { getRedisClient } from '@crowd/redis' -import { REDIS_CONFIG } from '../../conf' +import TenantService from '../tenantService' const db = null @@ -24,97 +22,6 @@ describe('TenantService tests', () => { await SequelizeTestUtils.closeConnection(db) }) - describe('findMembersToMerge', () => { - it('Should show the same merge suggestion once, with reverse order', async () => { - const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db) - const memberService = new MemberService(mockIServiceOptions) - const tenantService = new TenantService(mockIServiceOptions) - - const memberToCreate1 = { - username: { - [PlatformType.SLACK]: { - username: 'member 1', - integrationId: generateUUIDv1(), - }, - }, - platform: PlatformType.SLACK, - email: 'member.1@email.com', - joinedAt: '2020-05-27T15:13:30Z', - } - - const memberToCreate2 = { - username: { - [PlatformType.DISCORD]: { - username: 'member 2', - integrationId: generateUUIDv1(), - }, - }, - platform: PlatformType.DISCORD, - email: 'member.2@email.com', - joinedAt: '2020-05-26T15:13:30Z', - } - - const memberToCreate3 = { - username: { - [PlatformType.GITHUB]: { - username: 'member 3', - integrationId: generateUUIDv1(), - }, - }, - platform: PlatformType.GITHUB, - email: 'member.3@email.com', - joinedAt: '2020-05-25T15:13:30Z', - } - - const memberToCreate4 = { - username: { - [PlatformType.TWITTER]: { - username: 'member 4', - integrationId: generateUUIDv1(), - }, - }, - platform: PlatformType.TWITTER, - email: 'member.4@email.com', - joinedAt: '2020-05-24T15:13:30Z', - } - - const member1 = await memberService.upsert(memberToCreate1) - let member2 = await memberService.upsert(memberToCreate2) - const member3 = await memberService.upsert(memberToCreate3) - let member4 = await memberService.upsert(memberToCreate4) - - await memberService.addToMerge([{ members: [member1.id, member2.id], similarity: 1 }]) - await memberService.addToMerge([{ members: [member3.id, member4.id], similarity: 0.5 }]) - - member2 = await memberService.findById(member2.id) - member4 = await memberService.findById(member4.id) - - const memberToMergeSuggestions = await tenantService.findMembersToMerge({}) - - // In the DB there should be: - // - Member 1 should have member 2 in toMerge - // - Member 3 should have member 4 in toMerge - // - Member 4 should have member 3 in toMerge - // - We should get these 4 combinations - // But this function should not return duplicates, so we should get - // only two pairs: [m2, m1] and [m4, m3] - - expect(memberToMergeSuggestions.count).toEqual(1) - - expect( - memberToMergeSuggestions.rows[0].members - .sort((a, b) => (a.createdAt > b.createdAt ? 1 : -1)) - .map((m) => m.id), - ).toStrictEqual([member1.id, member2.id]) - - expect( - memberToMergeSuggestions.rows[1].members - .sort((a, b) => (a.createdAt > b.createdAt ? 1 : -1)) - .map((m) => m.id), - ).toStrictEqual([member3.id, member4.id]) - }) - }) - describe('_findAndCountAllForEveryUser method', () => { it('Should succesfully find all tenants without filtering by currentUser', async () => { let tenants = await TenantService._findAndCountAllForEveryUser({ filter: {} }) @@ -171,7 +78,7 @@ describe('TenantService tests', () => { id: tenantCreatedPlain.id, name: 'testName', url: 'testUrl', - plan: Plans.values.essential, + plan: null, isTrialPlan: false, trialEndsAt: null, onboardedAt: null, @@ -208,6 +115,7 @@ describe('TenantService tests', () => { expect(defaultAttributes.rows.map((i) => i.name).sort()).toEqual([ MemberAttributeName.BIO, MemberAttributeName.IS_BOT, + MemberAttributeName.IS_DELETED, MemberAttributeName.IS_ORGANIZATION, MemberAttributeName.IS_TEAM_MEMBER, MemberAttributeName.JOB_TITLE, diff --git a/backend/src/services/activityService.ts b/backend/src/services/activityService.ts index a9bca25e5c..9b85582b28 100644 --- a/backend/src/services/activityService.ts +++ b/backend/src/services/activityService.ts @@ -129,7 +129,12 @@ export default class ActivityService extends LoggerBase { data.sentiment = sentiment } - if (!data.username && data.platform === PlatformType.OTHER) { + if ( + !data.username && + (data.platform === PlatformType.OTHER || + // we have some custom platform types in db that are not in enum + !Object.values(PlatformType).includes(data.platform)) + ) { const { displayName } = await MemberRepository.findById(data.member, repositoryOptions) // Get the first key of the username object as a string data.username = displayName @@ -779,6 +784,18 @@ export default class ActivityService extends LoggerBase { return ActivityRepository.findAndCountAll(args, this.options) } + async queryV2(data) { + const filter = data.filter + const orderBy = Array.isArray(data.orderBy) ? data.orderBy : [data.orderBy] + const limit = data.limit + const offset = data.offset + const countOnly = data.countOnly ?? false + return ActivityRepository.findAndCountAllv2( + { filter, orderBy, limit, offset, countOnly }, + this.options, + ) + } + async query(data) { const memberAttributeSettings = ( await MemberAttributeSettingsRepository.findAndCountAll({}, this.options) diff --git a/backend/src/services/auth/authService.ts b/backend/src/services/auth/authService.ts index aa4a693e43..ccfa7203cd 100644 --- a/backend/src/services/auth/authService.ts +++ b/backend/src/services/auth/authService.ts @@ -119,7 +119,7 @@ class AuthService { existingUser.id, ) - return token + return { token, user: existingUser } } firstName = firstName || email.split('@')[0] @@ -187,7 +187,7 @@ class AuthService { await SequelizeRepository.commitTransaction(transaction) - return token + return { token, user: newUser } } catch (error) { await SequelizeRepository.rollbackTransaction(transaction) diff --git a/backend/src/services/dashboardService.ts b/backend/src/services/dashboardService.ts new file mode 100644 index 0000000000..983542940c --- /dev/null +++ b/backend/src/services/dashboardService.ts @@ -0,0 +1,81 @@ +import { DashboardTimeframe, FeatureFlag } from '@crowd/types' +import { RedisCache } from '@crowd/redis' +import { IServiceOptions } from './IServiceOptions' +import isFeatureEnabled from '@/feature-flags/isFeatureEnabled' + +interface IDashboardQueryParams { + segment?: string + platform?: string + timeframe: DashboardTimeframe +} + +export default class DashboardService { + options: IServiceOptions + + constructor(options) { + this.options = options + } + + async get(params: IDashboardQueryParams) { + if (!params.timeframe) { + throw new Error(`Timeframe is required!`) + } + + if (!Object.values(DashboardTimeframe).includes(params.timeframe)) { + throw new Error(`Unsupported timeframe ${params.timeframe}!`) + } + + const segmentsEnabled = await isFeatureEnabled(FeatureFlag.SEGMENTS, this.options) + + if (segmentsEnabled && !params.segment) { + throw new Error(`SegmentId is required in segment enabled deployments!`) + } + + // get default segment + if (!segmentsEnabled) { + params.segment = this.options.currentSegments[0].id + } + + let key = `${this.options.currentTenant.id}:${params.segment}:${params.timeframe}` + if (params.platform) { + key += `:${params.platform}` + } + + const cache = new RedisCache('dashboard-cache', this.options.redis, this.options.log) + const data = await cache.get(key) + + if (!data) { + return { + newMembers: { + total: 0, + previousPeriodTotal: 0, + timeseries: null, + }, + activeMembers: { + total: 0, + previousPeriodTotal: 0, + timeseries: null, + }, + newOrganizations: { + total: 0, + previousPeriodTotal: 0, + timeseries: null, + }, + activeOrganizations: { + total: 0, + previousPeriodTotal: 0, + timeseries: null, + }, + activity: { + total: 0, + previousPeriodTotal: 0, + timeseries: null, + bySentimentMood: null, + byTypeAndPlatform: null, + }, + } + } + + return JSON.parse(data) + } +} diff --git a/backend/src/services/integrationService.ts b/backend/src/services/integrationService.ts index 858840e4d1..382775774a 100644 --- a/backend/src/services/integrationService.ts +++ b/backend/src/services/integrationService.ts @@ -1200,12 +1200,18 @@ export default class IntegrationService { async gitConnectOrUpdate(integrationData) { const transaction = await SequelizeRepository.createTransaction(this.options) let integration + const stripGit = (url: string) => { + if (url.endsWith('.git')) { + return url.slice(0, -4) + } + return url + } try { integration = await this.createOrUpdate( { platform: PlatformType.GIT, settings: { - remotes: integrationData.remotes, + remotes: integrationData.remotes.map((remote) => stripGit(remote)), }, status: 'done', }, @@ -1580,4 +1586,81 @@ export default class IntegrationService { throw new Error400(this.options.language, 'errors.groupsio.invalidGroup') } } + + async connectYoutube(integrationData) { + this.options.log.info('Creating youtube integration!!') + let channelId = '' + let keywords = [] + let shouldVerifyChannelId = true + + const isValidKeyword = integrationData.keywords && Array.isArray(integrationData.keywords) + if (isValidKeyword && integrationData.keywords.length > 0) { + if (integrationData.keywords.length > 5) { + throw new Error400('The maximum number of keywords is 5') + } + + keywords = integrationData.keywords + shouldVerifyChannelId = false + } + + if (shouldVerifyChannelId) { + try { + const channelDetailsConfig: AxiosRequestConfig = { + method: 'get', + url: `https://www.googleapis.com/youtube/v3/channels`, + params: { + key: integrationData.apiKey, + id: integrationData.channelId, + part: 'contentDetails', + }, + } + + const response = (await axios(channelDetailsConfig)).data + const channelDetails = response.items[0] + channelId = channelDetails.id + } catch (err) { + throw new Error400( + `The channel: ${integrationData.channelId} with the api key: ${integrationData.apiKey} is not valid`, + ) + } + } + + let integration + const transaction = await SequelizeRepository.createTransaction(this.options) + + try { + integration = await this.createOrUpdate( + { + platform: PlatformType.YOUTUBE, + settings: { + apiKey: integrationData.apiKey, + channelId, + keywords, + page: 1, + }, + status: 'in-progress', + }, + transaction, + ) + + await SequelizeRepository.commitTransaction(transaction) + } catch (err) { + await SequelizeRepository.rollbackTransaction(transaction) + throw err + } + + this.options.log.info( + { tenantId: integration.tenantId }, + 'Sending Youtube message to int-run-worker!', + ) + const emitter = await getIntegrationRunWorkerEmitter() + await emitter.triggerIntegrationRun( + integration.tenantId, + integration.platform, + integration.id, + true, + ) + + return integration + } } diff --git a/backend/src/services/memberAffiliationService.ts b/backend/src/services/memberAffiliationService.ts index 28f29b5127..e41484e924 100644 --- a/backend/src/services/memberAffiliationService.ts +++ b/backend/src/services/memberAffiliationService.ts @@ -1,8 +1,9 @@ import { LoggerBase } from '@crowd/logging' +import { TemporalWorkflowId } from '@crowd/types' +import { WorkflowIdReusePolicy } from '@crowd/temporal' import { IServiceOptions } from './IServiceOptions' import MemberSegmentAffiliationRepository from '../database/repositories/memberSegmentAffiliationRepository' import MemberRepository from '../database/repositories/memberRepository' -import MemberAffiliationRepository from '../database/repositories/memberAffiliationRepository' export default class MemberAffiliationService extends LoggerBase { options: IServiceOptions @@ -53,6 +54,23 @@ export default class MemberAffiliationService extends LoggerBase { } async updateAffiliation(memberId: string) { - await MemberAffiliationRepository.update(memberId, this.options) + await this.options.temporal.workflow.start('memberUpdate', { + taskQueue: 'profiles', + workflowId: `${TemporalWorkflowId.MEMBER_UPDATE}/${this.options.currentTenant.id}/${memberId}`, + workflowIdReusePolicy: WorkflowIdReusePolicy.WORKFLOW_ID_REUSE_POLICY_TERMINATE_IF_RUNNING, + retry: { + maximumAttempts: 10, + }, + args: [ + { + member: { + id: memberId, + }, + }, + ], + searchAttributes: { + TenantId: [this.options.currentTenant.id], + }, + }) } } diff --git a/backend/src/services/memberOrganizationService.ts b/backend/src/services/memberOrganizationService.ts index c0543f87ec..1b2c1fcf17 100644 --- a/backend/src/services/memberOrganizationService.ts +++ b/backend/src/services/memberOrganizationService.ts @@ -67,7 +67,7 @@ export default class MemberOrganizationService extends LoggerBase { secondaryOrganizationId: string, primaryOrganizationId: string, ): Promise { - this.moveRolesBetweenEntities( + await this.moveRolesBetweenEntities( primaryOrganizationId, secondaryOrganizationId, OrgMergeStrat(primaryOrganizationId), @@ -75,7 +75,7 @@ export default class MemberOrganizationService extends LoggerBase { } async moveOrgsBetweenMembers(primaryMemberId: string, secondaryMemberId: string): Promise { - this.moveRolesBetweenEntities( + await this.moveRolesBetweenEntities( primaryMemberId, secondaryMemberId, MemberMergeStrat(primaryMemberId), diff --git a/backend/src/services/memberService.ts b/backend/src/services/memberService.ts index 4e0d04cac7..af0caba979 100644 --- a/backend/src/services/memberService.ts +++ b/backend/src/services/memberService.ts @@ -4,6 +4,7 @@ import { SERVICE, Error400, isDomainExcluded } from '@crowd/common' import { LoggerBase } from '@crowd/logging' import { WorkflowIdReusePolicy } from '@crowd/temporal' import { + ExportableEntity, FeatureFlag, IOrganization, ISearchSyncOptions, @@ -14,7 +15,8 @@ import { import lodash from 'lodash' import moment from 'moment-timezone' import validator from 'validator' -import { TEMPORAL_CONFIG } from '@/conf' +import { getOpensearchClient } from '@crowd/opensearch' +import { OPENSEARCH_CONFIG, TEMPORAL_CONFIG } from '@/conf' import { IRepositoryOptions } from '../database/repositories/IRepositoryOptions' import ActivityRepository from '../database/repositories/activityRepository' import MemberAttributeSettingsRepository from '../database/repositories/memberAttributeSettingsRepository' @@ -30,8 +32,6 @@ import { } from '../database/repositories/types/memberTypes' import isFeatureEnabled from '../feature-flags/isFeatureEnabled' import telemetryTrack from '../segment/telemetryTrack' -import { ExportableEntity } from '../serverless/microservices/nodejs/messageTypes' -import { sendExportCSVNodeSQSMessage } from '../serverless/utils/nodeWorkerSQS' import { IServiceOptions } from './IServiceOptions' import merge from './helpers/merge' import MemberAttributeSettingsService from './memberAttributeSettingsService' @@ -40,6 +40,7 @@ import SearchSyncService from './searchSyncService' import SettingsService from './settingsService' import { GITHUB_TOKEN_CONFIG } from '../conf' import { ServiceType } from '@/conf/configTypes' +import { getNodejsWorkerEmitter } from '@/serverless/utils/serviceSQS' import MemberOrganizationService from './memberOrganizationService' export default class MemberService extends LoggerBase { @@ -666,9 +667,6 @@ export default class MemberService extends LoggerBase { const memberOrganizationService = new MemberOrganizationService(repoOptions) await memberOrganizationService.moveOrgsBetweenMembers(originalId, toMergeId) - // update activities to belong to the originalId member - await MemberRepository.moveActivitiesBetweenMembers(toMergeId, originalId, repoOptions) - // Remove toMerge from original member await MemberRepository.removeToMerge(originalId, toMergeId, repoOptions) @@ -679,11 +677,20 @@ export default class MemberService extends LoggerBase { currentSegments: secondMemberSegments, }) - // Delete toMerge member - await MemberRepository.destroy(toMergeId, repoOptions, true) - await SequelizeRepository.commitTransaction(tx) + await this.options.temporal.workflow.start('finishMemberMerging', { + taskQueue: 'entity-merging', + workflowId: `finishMemberMerging/${originalId}/${toMergeId}`, + retry: { + maximumAttempts: 10, + }, + args: [originalId, toMergeId, this.options.currentTenant.id], + searchAttributes: { + TenantId: [this.options.currentTenant.id], + }, + }) + if (syncOptions.doSync) { try { const searchSyncService = new SearchSyncService(this.options, syncOptions.mode) @@ -791,6 +798,8 @@ export default class MemberService extends LoggerBase { return toKeep }, + attributes: (oldAttributes, newAttributes) => + MemberService.safeMerge(oldAttributes, newAttributes), }) } @@ -992,6 +1001,24 @@ export default class MemberService extends LoggerBase { const record = await MemberRepository.update(id, data, repoOptions) await SequelizeRepository.commitTransaction(transaction) + await this.options.temporal.workflow.start('memberUpdate', { + taskQueue: 'profiles', + workflowId: `${TemporalWorkflowId.MEMBER_UPDATE}/${this.options.currentTenant.id}/${id}`, + workflowIdReusePolicy: WorkflowIdReusePolicy.WORKFLOW_ID_REUSE_POLICY_TERMINATE_IF_RUNNING, + retry: { + maximumAttempts: 10, + }, + args: [ + { + member: { + id, + }, + }, + ], + searchAttributes: { + TenantId: [this.options.currentTenant.id], + }, + }) if (syncToOpensearch) { try { @@ -1129,6 +1156,10 @@ export default class MemberService extends LoggerBase { ) } + async findByIdOpensearch(id: string, segmentId?: string) { + return MemberRepository.findByIdOpensearch(id, this.options, segmentId) + } + async queryV2(data) { if (await isFeatureEnabled(FeatureFlag.SEGMENTS, this.options)) { if (data.segments.length !== 1) { @@ -1180,11 +1211,25 @@ export default class MemberService extends LoggerBase { } async queryForCsv(data) { - data.limit = 10000000000000 - const found = await this.query(data, true) + const transformed = { + filter: data.filter, + limit: data.limit || 200, + offset: data.offset || 0, + orderBy: data.orderBy, + countOnly: false, + segments: this.options.currentSegments.map((s) => s.id) || [], + attributesSettings: ( + await MemberAttributeSettingsRepository.findAndCountAll({}, this.options) + ).rows, + } + + const found = await MemberRepository.findAndCountAllOpensearch(transformed, { + ...this.options, + opensearch: getOpensearchClient(OPENSEARCH_CONFIG), + }) const relations = [ - { relation: 'organizations', attributes: ['name'] }, + { relation: 'organizations', attributes: ['displayName', 'website', 'logo'] }, { relation: 'notes', attributes: ['body'] }, { relation: 'tags', attributes: ['name'] }, ] @@ -1201,14 +1246,15 @@ export default class MemberService extends LoggerBase { } async export(data) { - const result = await sendExportCSVNodeSQSMessage( + const emitter = await getNodejsWorkerEmitter() + await emitter.exportCSV( this.options.currentTenant.id, this.options.currentUser.id, ExportableEntity.MEMBERS, SequelizeRepository.getSegmentIds(this.options), data, ) - return result + return {} } async findMembersWithMergeSuggestions(args) { @@ -1261,4 +1307,34 @@ export default class MemberService extends LoggerBase { out.total = lodash.sum(Object.values(out)) return out } + + /** + * Merges two objects, preserving non-null values in the original object. + * + * @param originalObject - The original object + * @param newObject - The object to merge into the original + * @returns The merged object + */ + static safeMerge(originalObject: any, newObject: any) { + const mergeCustomizer = (originalValue, newValue) => { + // Merge arrays, removing duplicates + if (lodash.isArray(originalValue)) { + return lodash.unionWith(originalValue, newValue, lodash.isEqual) + } + + // Recursively merge nested objects + if (lodash.isPlainObject(originalValue)) { + return lodash.mergeWith({}, originalValue, newValue, mergeCustomizer) + } + + // Preserve original non-null or non-empty values + if (newValue === null || (originalValue !== null && originalValue !== '')) { + return originalValue + } + + return undefined + } + + return lodash.mergeWith({}, originalObject, newObject, mergeCustomizer) + } } diff --git a/backend/src/services/organizationService.ts b/backend/src/services/organizationService.ts index 1c7c1baabd..81a99b4d01 100644 --- a/backend/src/services/organizationService.ts +++ b/backend/src/services/organizationService.ts @@ -1,4 +1,3 @@ -import { isEqual } from 'lodash' import { Error400, websiteNormalizer } from '@crowd/common' import { LoggerBase } from '@crowd/logging' import { @@ -8,8 +7,9 @@ import { OrganizationMergeSuggestionType, SyncMode, } from '@crowd/types' -import { IRepositoryOptions } from '@/database/repositories/IRepositoryOptions' +import { isEqual } from 'lodash' import getObjectWithoutKey from '@/utils/getObjectWithoutKey' +import { IRepositoryOptions } from '@/database/repositories/IRepositoryOptions' import MemberRepository from '../database/repositories/memberRepository' import { MergeActionState, @@ -20,7 +20,6 @@ import organizationCacheRepository from '../database/repositories/organizationCa import OrganizationRepository from '../database/repositories/organizationRepository' import SequelizeRepository from '../database/repositories/sequelizeRepository' import telemetryTrack from '../segment/telemetryTrack' -import { sendOrgMergeMessage } from '../serverless/utils/nodeWorkerSQS' import { IServiceOptions } from './IServiceOptions' import merge from './helpers/merge' import { @@ -28,8 +27,9 @@ import { keepPrimaryIfExists, mergeUniqueStringArrayItems, } from './helpers/mergeFunctions' -import SearchSyncService from './searchSyncService' import MemberOrganizationService from './memberOrganizationService' +import SearchSyncService from './searchSyncService' +import { IActiveOrganizationFilter } from '@/database/repositories/types/organizationTypes' export default class OrganizationService extends LoggerBase { options: IServiceOptions @@ -39,14 +39,6 @@ export default class OrganizationService extends LoggerBase { this.options = options } - async mergeAsync(originalId, toMergeId) { - const tenantId = this.options.currentTenant.id - - await MergeActionsRepository.add(MergeActionType.ORG, originalId, toMergeId, this.options) - - await sendOrgMergeMessage(tenantId, originalId, toMergeId) - } - async mergeSync(originalId, toMergeId) { this.options.log.info({ originalId, toMergeId }, 'Merging organizations!') @@ -73,22 +65,14 @@ export default class OrganizationService extends LoggerBase { } } - const mergeStatusChanged = await MergeActionsRepository.setState( + await MergeActionsRepository.add( MergeActionType.ORG, originalId, toMergeId, - MergeActionState.IN_PROGRESS, // not using transaction here on purpose, // so this change is visible until we finish this.options, ) - if (!mergeStatusChanged) { - this.log.info('[Merge Organizations] - Merging already in progress!') - return { - status: 203, - mergedId: originalId, - } - } const repoOptions: IRepositoryOptions = await SequelizeRepository.createTransactionalRepositoryOptions(this.options) @@ -155,13 +139,6 @@ export default class OrganizationService extends LoggerBase { const memberOrganizationService = new MemberOrganizationService(repoOptions) await memberOrganizationService.moveMembersBetweenOrganizations(toMergeId, originalId) - // update activities that belong to source org to destination org - await OrganizationRepository.moveActivitiesBetweenOrganizations( - toMergeId, - originalId, - repoOptions, - ) - const secondMemberSegments = await OrganizationRepository.getOrganizationSegments( toMergeId, repoOptions, @@ -174,32 +151,57 @@ export default class OrganizationService extends LoggerBase { }) } - // Delete toMerge organization - await OrganizationRepository.destroy(toMergeId, repoOptions, true, false) - await SequelizeRepository.commitTransaction(tx) await MergeActionsRepository.setState( MergeActionType.ORG, originalId, toMergeId, - MergeActionState.DONE, + MergeActionState.FINISHING, this.options, ) - const searchSyncService = new SearchSyncService(this.options) + const searchSyncService = new SearchSyncService(this.options, SyncMode.ASYNCHRONOUS) await searchSyncService.triggerOrganizationSync(this.options.currentTenant.id, originalId) await searchSyncService.triggerRemoveOrganization(this.options.currentTenant.id, toMergeId) // sync organization members - await searchSyncService.triggerOrganizationMembersSync(originalId) + await searchSyncService.triggerOrganizationMembersSync( + this.options.currentTenant.id, + originalId, + ) // sync organization activities - await searchSyncService.triggerOrganizationActivitiesSync(originalId) + await searchSyncService.triggerOrganizationActivitiesSync( + this.options.currentTenant.id, + originalId, + ) + + await this.options.temporal.workflow.start('finishOrganizationMerging', { + taskQueue: 'entity-merging', + workflowId: `finishOrganizationMerging/${originalId}/${toMergeId}`, + retry: { + maximumAttempts: 10, + }, + args: [ + originalId, + toMergeId, + original.displayName, + toMerge.displayName, + this.options.currentTenant.id, + this.options.currentUser.id, + ], + searchAttributes: { + TenantId: [this.options.currentTenant.id], + }, + }) this.options.log.info({ originalId, toMergeId }, 'Organizations merged!') - return { status: 200, mergedId: originalId } + return { + status: 200, + mergedId: originalId, + } } catch (err) { this.options.log.error(err, 'Error while merging organizations!', { originalId, @@ -402,17 +404,33 @@ export default class OrganizationService extends LoggerBase { const primaryIdentity = data.identities[0] const nameToCheckInCache = (data as any).name || primaryIdentity.name - // check cache existing by name - let cache = await organizationCacheRepository.findByName(nameToCheckInCache, { - ...this.options, - transaction, - }) - // Normalize the website URL if it exists if (data.website) { data.website = websiteNormalizer(data.website) } + // lets check if we have this organization in cache by website + let cache + let createCacheIdentity = false + if (data.website) { + cache = await organizationCacheRepository.findByWebsite(data.website, { + ...this.options, + transaction, + }) + + if (cache && !cache.names.includes(nameToCheckInCache)) { + createCacheIdentity = true + } + } + + // check cache existing by name + if (!cache) { + cache = await organizationCacheRepository.findByName(nameToCheckInCache, { + ...this.options, + transaction, + }) + } + // if cache exists, merge current data with cache data // if it doesn't exist, create it from incoming data if (cache) { @@ -443,10 +461,15 @@ export default class OrganizationService extends LoggerBase { } }) if (Object.keys(updateData).length > 0) { - await organizationCacheRepository.update(cache.id, updateData, { - ...this.options, - transaction, - }) + await organizationCacheRepository.update( + cache.id, + updateData, + { + ...this.options, + transaction, + }, + createCacheIdentity ? nameToCheckInCache : undefined, + ) cache = { ...cache, ...updateData } // Update the cached data with the new data } @@ -491,7 +514,7 @@ export default class OrganizationService extends LoggerBase { } if (!existing) { - existing = await OrganizationRepository.findByIdentity(primaryIdentity, this.options) + existing = await OrganizationRepository.findByIdentities(data.identities, this.options) } if (existing) { @@ -583,6 +606,11 @@ export default class OrganizationService extends LoggerBase { } } + await organizationCacheRepository.linkCacheAndOrganization(cache.id, record.id, { + ...this.options, + transaction, + }) + await SequelizeRepository.commitTransaction(transaction) if (syncOptions.doSync) { @@ -604,7 +632,13 @@ export default class OrganizationService extends LoggerBase { return OrganizationRepository.findOrganizationsWithMergeSuggestions(args, this.options) } - async update(id, data, overrideIdentities = false, syncToOpensearch = true) { + async update( + id, + data, + overrideIdentities = false, + syncToOpensearch = true, + manualChange = false, + ) { let tx try { @@ -646,7 +680,13 @@ export default class OrganizationService extends LoggerBase { } } - const record = await OrganizationRepository.update(id, data, repoOptions, overrideIdentities) + const record = await OrganizationRepository.update( + id, + data, + repoOptions, + overrideIdentities, + manualChange, + ) await SequelizeRepository.commitTransaction(tx) @@ -716,6 +756,23 @@ export default class OrganizationService extends LoggerBase { return OrganizationRepository.findAndCountAll(args, this.options) } + async findAndCountActive( + filters: IActiveOrganizationFilter, + offset: number, + limit: number, + orderBy: string, + segments: string[], + ) { + return OrganizationRepository.findAndCountActiveOpensearch( + filters, + limit, + offset, + orderBy, + this.options, + segments, + ) + } + async findByUrl(url) { return OrganizationRepository.findByUrl(url, this.options) } @@ -724,6 +781,10 @@ export default class OrganizationService extends LoggerBase { return OrganizationRepository.findOrCreateByDomain(domain, this.options) } + async findByIdOpensearch(id: string, segmentId?: string) { + return OrganizationRepository.findByIdOpensearch(id, this.options, segmentId) + } + async query(data) { const advancedFilter = data.filter const orderBy = data.orderBy diff --git a/backend/src/services/premium/enrichment/memberEnrichmentService.ts b/backend/src/services/premium/enrichment/memberEnrichmentService.ts index 908b19497f..271d84d54a 100644 --- a/backend/src/services/premium/enrichment/memberEnrichmentService.ts +++ b/backend/src/services/premium/enrichment/memberEnrichmentService.ts @@ -13,15 +13,9 @@ import { PlatformType, OrganizationSource, SyncMode, + IOrganizationIdentity, + TemporalWorkflowId, } from '@crowd/types' -import { ENRICHMENT_CONFIG, REDIS_CONFIG } from '../../../conf' -import { AttributeData } from '../../../database/attributes/attribute' -import MemberEnrichmentCacheRepository from '../../../database/repositories/memberEnrichmentCacheRepository' -import track from '../../../segment/track' -import { Member } from '../../../serverless/integrations/types/messageTypes' -import { IServiceOptions } from '../../IServiceOptions' -import MemberAttributeSettingsService from '../../memberAttributeSettingsService' -import MemberService from '../../memberService' import { EnrichmentAPICertification, EnrichmentAPIContribution, @@ -30,7 +24,15 @@ import { EnrichmentAPIResponse, EnrichmentAPISkills, EnrichmentAPIWorkExperience, -} from './types/memberEnrichmentTypes' +} from '@crowd/types/premium' +import { WorkflowIdReusePolicy } from '@crowd/temporal' +import { ENRICHMENT_CONFIG, REDIS_CONFIG } from '../../../conf' +import { AttributeData } from '../../../database/attributes/attribute' +import MemberEnrichmentCacheRepository from '../../../database/repositories/memberEnrichmentCacheRepository' +import { Member } from '../../../serverless/integrations/types/messageTypes' +import { IServiceOptions } from '../../IServiceOptions' +import MemberAttributeSettingsService from '../../memberAttributeSettingsService' +import MemberService from '../../memberService' import OrganizationService from '../../organizationService' import MemberRepository from '../../../database/repositories/memberRepository' import OrganizationRepository from '../../../database/repositories/organizationRepository' @@ -144,7 +146,6 @@ export default class MemberEnrichmentService extends LoggerBase { async bulkEnrich(memberIds: string[], notifyFrontend: boolean = true) { const redis = await getRedisClient(REDIS_CONFIG, true) - const searchSyncService = new SearchSyncService(this.options, SyncMode.ASYNCHRONOUS) const apiPubSubEmitter = new RedisPubSubEmitter( 'api-pubsub', @@ -159,7 +160,6 @@ export default class MemberEnrichmentService extends LoggerBase { try { await this.enrichOne(memberId) enrichedMembers++ - await searchSyncService.triggerMemberSync(this.options.currentTenant.id, memberId) this.log.info(`Enriched member ${memberId}`) } catch (err) { if ( @@ -223,12 +223,8 @@ export default class MemberEnrichmentService extends LoggerBase { * @param memberId - the ID of the member to enrich * @returns a promise that resolves to the enrichment data for the member */ - async enrichOne(memberId) { + async enrichOne(memberId, syncMode = SyncMode.ASYNCHRONOUS) { const transaction = await SequelizeRepository.createTransaction(this.options) - const options = { - ...this.options, - transaction, - } try { // If the attributes have not been fetched yet, fetch them @@ -236,10 +232,10 @@ export default class MemberEnrichmentService extends LoggerBase { await this.getAttributes() } - const searchSyncService = new SearchSyncService(this.options, SyncMode.ASYNCHRONOUS) + const searchSyncService = new SearchSyncService(this.options, syncMode) // Create an instance of the MemberService and use it to look up the member - const memberService = new MemberService(options) + const memberService = new MemberService(this.options) const member = await memberService.findById(memberId, false, false) // If the member's GitHub handle or email address is not available, throw an error @@ -247,16 +243,13 @@ export default class MemberEnrichmentService extends LoggerBase { throw new Error400(this.options.language, 'enrichment.errors.noGithubHandleOrEmail') } - let enrichedFrom = '' let enrichmentData: EnrichmentAPIMember // If the member has a GitHub handle, use it to make a request to the Enrichment API if (member.username[PlatformType.GITHUB]) { - enrichedFrom = 'github' enrichmentData = await this.getEnrichmentByGithubHandle( member.username[PlatformType.GITHUB][0], ) } else if (member.emails.length > 0) { - enrichedFrom = 'email' // If the member has an email address, use it to make a request to the Enrichment API enrichmentData = await this.getEnrichmentByEmail(member.emails[0]) } @@ -289,7 +282,7 @@ export default class MemberEnrichmentService extends LoggerBase { // add the member to merge suggestions await MemberRepository.addToMerge( [{ similarity: 0.9, members: [memberId, existingMember.id] }], - options, + this.options, ) if (Array.isArray(normalized.username[platform])) { @@ -310,8 +303,7 @@ export default class MemberEnrichmentService extends LoggerBase { } // save raw data to cache - await MemberEnrichmentCacheRepository.upsert(memberId, enrichmentData, options) - + await MemberEnrichmentCacheRepository.upsert(memberId, enrichmentData, this.options) // We are updating the displayName only if the existing one has one word only // And we are using an update here instead of the upsert because // upsert always takes the existing displayName @@ -327,15 +319,6 @@ export default class MemberEnrichmentService extends LoggerBase { } } - track( - 'Member Enriched', - { - memberId: member.id, - enrichedFrom, - }, - options, - ) - let result = await memberService.upsert( { ...normalized, @@ -349,21 +332,31 @@ export default class MemberEnrichmentService extends LoggerBase { // for every work experience in `enrichmentData` // - upsert organization // - upsert `memberOrganization` relation - const organizationService = new OrganizationService(options) + const organizationService = new OrganizationService(this.options) if (enrichmentData.work_experiences) { for (const workExperience of enrichmentData.work_experiences) { + const organizationIdentities: IOrganizationIdentity[] = [ + { + name: workExperience.company, + platform: PlatformType.ENRICHMENT, + }, + ] + + if (workExperience.companyLinkedInUrl) { + organizationIdentities.push({ + name: workExperience.companyLinkedInUrl.split('/').pop(), + platform: PlatformType.LINKEDIN, + url: workExperience.companyLinkedInUrl, + }) + } + const org = await organizationService.createOrUpdate( { - identities: [ - { - name: workExperience.company, - platform: PlatformType.ENRICHMENT, - }, - ], + identities: organizationIdentities, }, { doSync: true, - mode: SyncMode.ASYNCHRONOUS, + mode: syncMode, }, ) @@ -379,17 +372,40 @@ export default class MemberEnrichmentService extends LoggerBase { dateEnd, source: OrganizationSource.ENRICHMENT, } - await MemberRepository.createOrUpdateWorkExperience(data, options) - await OrganizationRepository.includeOrganizationToSegments(org.id, options) + await MemberRepository.createOrUpdateWorkExperience(data, this.options) + await OrganizationRepository.includeOrganizationToSegments(org.id, this.options) } } + await SequelizeRepository.commitTransaction(transaction) + if (enrichmentData.work_experiences) { + await this.options.temporal.workflow.start('memberUpdate', { + taskQueue: 'profiles', + workflowId: `${TemporalWorkflowId.MEMBER_UPDATE}/${this.options.currentTenant.id}/${result.id}`, + workflowIdReusePolicy: + WorkflowIdReusePolicy.WORKFLOW_ID_REUSE_POLICY_TERMINATE_IF_RUNNING, + retry: { + maximumAttempts: 10, + }, + args: [ + { + member: { + id: result.id, + }, + }, + ], + searchAttributes: { + TenantId: [this.options.currentTenant.id], + }, + }) + } + await searchSyncService.triggerMemberSync(this.options.currentTenant.id, result.id) - result = await memberService.findById(result.id, true, false) - await SequelizeRepository.commitTransaction(transaction) + result = await MemberRepository.findByIdOpensearch(result.id, this.options) return result } catch (error) { + this.log.error(error, 'Error while enriching a member!') await SequelizeRepository.rollbackTransaction(transaction) throw error } @@ -511,7 +527,6 @@ export default class MemberEnrichmentService extends LoggerBase { // Assign 'value' to 'member.attributes[attributeName].enrichment' member.attributes[attributeName].enrichment = value - await this.createAttributeAndUpdateOptions(attributeName, attribute, value) } } diff --git a/backend/src/services/premium/enrichment/organizationEnrichmentService.ts b/backend/src/services/premium/enrichment/organizationEnrichmentService.ts index dedb033d0a..ef024e19b4 100644 --- a/backend/src/services/premium/enrichment/organizationEnrichmentService.ts +++ b/backend/src/services/premium/enrichment/organizationEnrichmentService.ts @@ -11,11 +11,11 @@ import { PlatformType, SyncMode, } from '@crowd/types' +import { renameKeys } from '@crowd/common' +import { EnrichmentParams, IEnrichmentResponse } from '../../../types/enrichmentTypes' import { REDIS_CONFIG } from '../../../conf' import OrganizationRepository from '../../../database/repositories/organizationRepository' -import { renameKeys } from '../../../utils/renameKeys' import { IServiceOptions } from '../../IServiceOptions' -import { EnrichmentParams, IEnrichmentResponse } from './types/organizationEnrichmentTypes' import SequelizeRepository from '@/database/repositories/sequelizeRepository' import SearchSyncService from '@/services/searchSyncService' @@ -304,6 +304,7 @@ export default class OrganizationEnrichmentService extends LoggerBase { ): IOrganization { let data = renameKeys(pdlData, { summary: 'description', + display_name: 'displayName', employee_count_by_country: 'employeeCountByCountry', employee_count: 'employees', location: 'address', diff --git a/backend/src/services/searchSyncService.ts b/backend/src/services/searchSyncService.ts index 8ce3c5469b..aaac0d5828 100644 --- a/backend/src/services/searchSyncService.ts +++ b/backend/src/services/searchSyncService.ts @@ -1,7 +1,7 @@ import { LoggerBase } from '@crowd/logging' import { SearchSyncApiClient } from '@crowd/opensearch' -import { SearchSyncWorkerEmitter } from '@crowd/sqs' import { FeatureFlag, SyncMode } from '@crowd/types' +import { SearchSyncWorkerEmitter } from '@crowd/common_services' import { getSearchSyncApiClient } from '../utils/apiClients' import { getSearchSyncWorkerEmitter } from '@/serverless/utils/serviceSQS' import isFeatureEnabled from '@/feature-flags/isFeatureEnabled' @@ -52,7 +52,7 @@ export default class SearchSyncService extends LoggerBase { if (client instanceof SearchSyncApiClient) { await client.triggerMemberSync(memberId) } else if (client instanceof SearchSyncWorkerEmitter) { - await client.triggerMemberSync(tenantId, memberId) + await client.triggerMemberSync(tenantId, memberId, false) } else { throw new Error('Unexpected search client type!') } @@ -68,11 +68,11 @@ export default class SearchSyncService extends LoggerBase { } } - async triggerOrganizationMembersSync(organizationId: string) { + async triggerOrganizationMembersSync(tenantId: string, organizationId: string) { const client = await this.getSearchSyncClient() if (client instanceof SearchSyncApiClient || client instanceof SearchSyncWorkerEmitter) { - await client.triggerOrganizationMembersSync(organizationId) + await client.triggerOrganizationMembersSync(tenantId, organizationId, false) } else { throw new Error('Unexpected search client type!') } @@ -84,7 +84,7 @@ export default class SearchSyncService extends LoggerBase { if (client instanceof SearchSyncApiClient) { await client.triggerRemoveMember(memberId) } else if (client instanceof SearchSyncWorkerEmitter) { - await client.triggerRemoveMember(tenantId, memberId) + await client.triggerRemoveMember(tenantId, memberId, false) } else { throw new Error('Unexpected search client type!') } @@ -106,7 +106,7 @@ export default class SearchSyncService extends LoggerBase { if (client instanceof SearchSyncApiClient) { await client.triggerActivitySync(activityId) } else if (client instanceof SearchSyncWorkerEmitter) { - await client.triggerActivitySync(tenantId, activityId) + await client.triggerActivitySync(tenantId, activityId, false) } else { throw new Error('Unexpected search client type!') } @@ -122,11 +122,11 @@ export default class SearchSyncService extends LoggerBase { } } - async triggerOrganizationActivitiesSync(organizationId: string) { + async triggerOrganizationActivitiesSync(tenantId: string, organizationId: string) { const client = await this.getSearchSyncClient() if (client instanceof SearchSyncApiClient || client instanceof SearchSyncWorkerEmitter) { - await client.triggerOrganizationActivitiesSync(organizationId) + await client.triggerOrganizationActivitiesSync(tenantId, organizationId, false) } else { throw new Error('Unexpected search client type!') } @@ -138,7 +138,7 @@ export default class SearchSyncService extends LoggerBase { if (client instanceof SearchSyncApiClient) { await client.triggerRemoveActivity(activityId) } else if (client instanceof SearchSyncWorkerEmitter) { - await client.triggerRemoveActivity(tenantId, activityId) + await client.triggerRemoveActivity(tenantId, activityId, false) } else { throw new Error('Unexpected search client type!') } @@ -160,7 +160,7 @@ export default class SearchSyncService extends LoggerBase { if (client instanceof SearchSyncApiClient) { await client.triggerOrganizationSync(organizationId) } else if (client instanceof SearchSyncWorkerEmitter) { - await client.triggerOrganizationSync(tenantId, organizationId) + await client.triggerOrganizationSync(tenantId, organizationId, false) } else { throw new Error('Unexpected search client type!') } @@ -182,7 +182,7 @@ export default class SearchSyncService extends LoggerBase { if (client instanceof SearchSyncApiClient) { await client.triggerRemoveOrganization(organizationId) } else if (client instanceof SearchSyncWorkerEmitter) { - await client.triggerRemoveOrganization(tenantId, organizationId) + await client.triggerRemoveOrganization(tenantId, organizationId, false) } else { throw new Error('Unexpected search client type!') } diff --git a/backend/src/services/slackCommandService.ts b/backend/src/services/slackCommandService.ts index 676ea39cf2..4fd6fc8773 100644 --- a/backend/src/services/slackCommandService.ts +++ b/backend/src/services/slackCommandService.ts @@ -1,8 +1,9 @@ /* eslint-disable no-case-declarations */ import { validateUUID as uuidValidate } from '@crowd/common' +import { TenantPlans } from '@crowd/types' import moment from 'moment' -import { Section, Message, SlackMessageDto, Divider } from 'slack-block-builder' -import { IS_DEV_ENV, IS_STAGING_ENV, IS_PROD_ENV } from '../conf' +import { Divider, Message, Section, SlackMessageDto } from 'slack-block-builder' +import { IS_DEV_ENV, IS_PROD_ENV, IS_STAGING_ENV } from '../conf' import TenantRepository from '../database/repositories/tenantRepository' import { SlackCommand, @@ -12,7 +13,6 @@ import { SlackParameterParseResult, } from '../types/slackTypes' import { IServiceOptions } from './IServiceOptions' -import Plans from '../security/plans' export default class SlackCommandService { private readonly commands: SlackCommandDefinition[] @@ -57,7 +57,7 @@ export default class SlackCommandService { required: true, description: 'Plan to set', type: SlackCommandParameterType.STRING, - allowedValues: [Plans.values.growth, Plans.values.essential], + allowedValues: [TenantPlans.Growth, TenantPlans.Essential], }, { name: 'trialEndsAt', diff --git a/backend/src/services/stripeService.ts b/backend/src/services/stripeService.ts new file mode 100644 index 0000000000..e9e17699d0 --- /dev/null +++ b/backend/src/services/stripeService.ts @@ -0,0 +1,36 @@ +import { Stripe } from 'stripe' +import { TenantPlans } from '@crowd/types' +import { PLANS_CONFIG } from '@/conf' + +const stripe = new Stripe(PLANS_CONFIG.stripeSecretKey, { + apiVersion: '2022-08-01', + typescript: true, +}) + +class StripeService { + static async retreiveSession(sessionId: string) { + return stripe.checkout.sessions.retrieve(sessionId) + } + + static async retreiveSubscription(subscriptionId: string) { + return stripe.subscriptions.retrieve(subscriptionId) + } + + static getPlanFromProductId(productId: string) { + if (productId === PLANS_CONFIG.stripeScalePlanProductId) { + return TenantPlans.Scale + } + if (productId === PLANS_CONFIG.stripeEssentialPlanProductId) { + return TenantPlans.Essential + } + if (productId === PLANS_CONFIG.stripeEagleEyePlanProductId) { + return TenantPlans.EagleEye + } + if (productId === PLANS_CONFIG.stripeGrowthPlanProductId) { + return TenantPlans.Growth + } + return null + } +} + +export default StripeService diff --git a/backend/src/services/tenantService.ts b/backend/src/services/tenantService.ts index 89c2f4a354..821482f179 100644 --- a/backend/src/services/tenantService.ts +++ b/backend/src/services/tenantService.ts @@ -1,6 +1,7 @@ import { DEFAULT_MEMBER_ATTRIBUTES } from '@crowd/integrations' -import { SegmentData, SegmentStatus } from '@crowd/types' +import { SegmentData, SegmentStatus, TenantPlans } from '@crowd/types' import { Error400, Error404 } from '@crowd/common' +import moment from 'moment/moment' import { TENANT_MODE } from '../conf/index' import TenantRepository from '../database/repositories/tenantRepository' import TenantUserRepository from '../database/repositories/tenantUserRepository' @@ -27,6 +28,7 @@ import SegmentService from './segmentService' import OrganizationService from './organizationService' import { defaultCustomViews } from '@/types/customView' import CustomViewRepository from '@/database/repositories/customViewRepository' +import StripeService from '@/services/stripeService' export default class TenantService { options: IServiceOptions @@ -388,7 +390,7 @@ export default class TenantService { } async updatePlanToFree(planStripeCustomerId) { - return this.updatePlanStatus(planStripeCustomerId, Plans.values.essential, 'active') + return this.updatePlanStatus(planStripeCustomerId, TenantPlans.Essential, 'active') } async updatePlanStatus(planStripeCustomerId, plan, planStatus) { @@ -588,4 +590,32 @@ export default class TenantService { const organizationService = new OrganizationService(this.options) return organizationService.findOrganizationsWithMergeSuggestions(args) } + + async confirmPayment(tenantId: string, args) { + const { sessionId } = args + const session = await StripeService.retreiveSession(sessionId) + const subscription = await StripeService.retreiveSubscription( + (session.subscription as any)?.id ?? session.subscription, + ) + + const productId = (subscription as any).plan.product + + const trialEnd = subscription.trial_end + + const subscriptionEndsAt = subscription.current_period_end + + const productPlan = StripeService.getPlanFromProductId(productId) + + if (!productPlan) { + throw new Error404() + } + + return this.update(tenantId, { + plan: productPlan, + isTrialPlan: !!trialEnd, + trialEndsAt: trialEnd ? moment(trialEnd, 'X').toISOString() : null, + stripeSubscriptionId: subscription.id, + planSubscriptionEndsAt: moment(subscriptionEndsAt, 'X').toISOString(), + }) + } } diff --git a/backend/src/services/user/__tests__/permissionChecker.test.ts b/backend/src/services/user/__tests__/permissionChecker.test.ts index 7b5f9e0b6a..40cb594f37 100644 --- a/backend/src/services/user/__tests__/permissionChecker.test.ts +++ b/backend/src/services/user/__tests__/permissionChecker.test.ts @@ -1,4 +1,4 @@ -import { PlatformType } from '@crowd/types' +import { PlatformType, TenantPlans } from '@crowd/types' import { Error403 } from '@crowd/common' import SequelizeTestUtils from '../../../database/utils/sequelizeTestUtils' import Plans from '../../../security/plans' @@ -18,8 +18,11 @@ describe('PermissionChecker tests', () => { describe('Integration protected fields', () => { it('Should throw an error when limitCount is passed', async () => { - for (const plan of Object.values(Plans.values)) { - const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db, plan) + for (const plan of Object.values(TenantPlans)) { + const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions( + db, + plan as TenantPlans, + ) const permissionChecker = new PermissionChecker(mockIServiceOptions) const data = { limitCount: 1, @@ -33,8 +36,11 @@ describe('PermissionChecker tests', () => { }) it('Should throw an error when limitCount is passed as 0', async () => { - for (const plan of Object.values(Plans.values)) { - const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions(db, plan) + for (const plan of Object.values(TenantPlans)) { + const mockIServiceOptions = await SequelizeTestUtils.getTestIServiceOptions( + db, + plan as TenantPlans, + ) const permissionChecker = new PermissionChecker(mockIServiceOptions) const data = { limitCount: 0, diff --git a/backend/src/services/user/permissionChecker.ts b/backend/src/services/user/permissionChecker.ts index ac5970d00d..89c1655a9b 100644 --- a/backend/src/services/user/permissionChecker.ts +++ b/backend/src/services/user/permissionChecker.ts @@ -1,11 +1,9 @@ import assert from 'assert' import { Error400, Error403 } from '@crowd/common' -import Plans from '../../security/plans' +import { TenantPlans } from '@crowd/types' import Permissions from '../../security/permissions' import EmailSender from '../emailSender' -const plans = Plans.values - /** * Checks the Permission of the User on a Tenant. */ @@ -164,7 +162,7 @@ export default class PermissionChecker { */ get currentTenantPlan() { if (!this.currentTenant || !this.currentTenant.plan) { - return plans.essential + return TenantPlans.Essential } return this.currentTenant.plan diff --git a/backend/src/services/user/userDestroyer.ts b/backend/src/services/user/userDestroyer.ts index 9c27048307..dfd6464c72 100644 --- a/backend/src/services/user/userDestroyer.ts +++ b/backend/src/services/user/userDestroyer.ts @@ -1,9 +1,9 @@ -import assert from 'assert' import { Error400 } from '@crowd/common' +import { TenantPlans } from '@crowd/types' +import assert from 'assert' import SequelizeRepository from '../../database/repositories/sequelizeRepository' -import UserRepository from '../../database/repositories/userRepository' import TenantUserRepository from '../../database/repositories/tenantUserRepository' -import Plans from '../../security/plans' +import UserRepository from '../../database/repositories/userRepository' import { IServiceOptions } from '../IServiceOptions' /** @@ -65,7 +65,7 @@ export default class UserDestroyer { async _isRemovingPlanUser() { const { currentTenant } = this.options - if (currentTenant.plan === Plans.values.essential) { + if (currentTenant.plan === TenantPlans.Essential) { return false } diff --git a/backend/src/services/user/userEditor.ts b/backend/src/services/user/userEditor.ts index d1dbe48ebb..5bddd9ac2d 100644 --- a/backend/src/services/user/userEditor.ts +++ b/backend/src/services/user/userEditor.ts @@ -1,10 +1,10 @@ -import assert from 'assert' import { Error400 } from '@crowd/common' -import Roles from '../../security/roles' +import { TenantPlans } from '@crowd/types' +import assert from 'assert' import SequelizeRepository from '../../database/repositories/sequelizeRepository' -import UserRepository from '../../database/repositories/userRepository' import TenantUserRepository from '../../database/repositories/tenantUserRepository' -import Plans from '../../security/plans' +import UserRepository from '../../database/repositories/userRepository' +import Roles from '../../security/roles' import { IServiceOptions } from '../IServiceOptions' /** @@ -86,7 +86,7 @@ export default class UserEditor { const { currentTenant } = this.options - if (currentTenant.plan === Plans.values.essential) { + if (currentTenant.plan === TenantPlans.Essential) { return false } diff --git a/backend/src/services/premium/enrichment/types/organizationEnrichmentTypes.ts b/backend/src/types/enrichmentTypes.ts similarity index 96% rename from backend/src/services/premium/enrichment/types/organizationEnrichmentTypes.ts rename to backend/src/types/enrichmentTypes.ts index 16de50f64c..08a8e0869d 100644 --- a/backend/src/services/premium/enrichment/types/organizationEnrichmentTypes.ts +++ b/backend/src/types/enrichmentTypes.ts @@ -1,6 +1,7 @@ import { IOrganizationIdentity } from '@crowd/types' import { CompanyEnrichmentParams, CompanyResponse } from 'peopledatalabs' +// eslint-disable-next-line @typescript-eslint/no-explicit-any export type IEnrichmentResponse = CompanyResponse & { address?: any; geoLocation?: string } export type EnrichmentParams = CompanyEnrichmentParams @@ -30,7 +31,7 @@ export interface IOrganization { linkedin?: ISocialNetwork crunchbase?: ISocialNetwork lastEnrichedAt?: Date - geoLocation?: String + geoLocation?: string address?: IEnrichmentResponse['location'] ultimateParent: IEnrichmentResponse['ultimate_parent'] immediateParent: IEnrichmentResponse['immediate_parent'] diff --git a/backend/src/types/mq/nodeWorkerIntegrationProcessMessage.ts b/backend/src/types/mq/nodeWorkerIntegrationProcessMessage.ts deleted file mode 100644 index ee1481010c..0000000000 --- a/backend/src/types/mq/nodeWorkerIntegrationProcessMessage.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { NodeWorkerMessageType } from '../../serverless/types/workerTypes' -import { NodeWorkerMessageBase } from './nodeWorkerMessageBase' -import { IIntegrationStream } from '../integration/stepResult' - -export interface IIntegrationStreamRetry { - id: string - stream: IIntegrationStream - retryCount: number -} - -export class NodeWorkerIntegrationProcessMessage extends NodeWorkerMessageBase { - constructor( - public readonly runId: string, - public readonly streamId?: string, - public readonly fireCrowdWebhooks?: boolean, - ) { - super(NodeWorkerMessageType.INTEGRATION_PROCESS) - } -} diff --git a/backend/src/types/mq/nodeWorkerProcessWebhookMessage.ts b/backend/src/types/mq/nodeWorkerProcessWebhookMessage.ts deleted file mode 100644 index 1c08543ae7..0000000000 --- a/backend/src/types/mq/nodeWorkerProcessWebhookMessage.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { NodeWorkerMessageType } from '../../serverless/types/workerTypes' -import { NodeWorkerMessageBase } from './nodeWorkerMessageBase' - -export class NodeWorkerProcessWebhookMessage extends NodeWorkerMessageBase { - constructor( - public readonly tenantId: string, - public readonly webhookId: string, - public readonly force?: boolean, - public readonly fireCrowdWebhooks?: boolean, - ) { - super(NodeWorkerMessageType.PROCESS_WEBHOOK) - } -} diff --git a/backend/src/utils/renameKeys.ts b/backend/src/utils/renameKeys.ts deleted file mode 100644 index 0e39cdd4f0..0000000000 --- a/backend/src/utils/renameKeys.ts +++ /dev/null @@ -1,10 +0,0 @@ -type RemapT = { [index: string]: any } - -export const renameKeys = (obj: RemapT, fieldMap: RemapT): T => - Object.keys(obj).reduce( - (acc, key) => ({ - ...acc, - ...{ [fieldMap[key] || key]: obj[key] }, - }), - {} as T, - ) diff --git a/backend/tsconfig.json b/backend/tsconfig.json index 8a3540a639..1e2b3ed554 100644 --- a/backend/tsconfig.json +++ b/backend/tsconfig.json @@ -13,6 +13,7 @@ "types": ["node", "jest"], "baseUrl": "./src", "paths": { + "@crowd/*/premium": ["../../services/libs/*/src/premium"], "@crowd/*": ["../../services/libs/*/src"], "@/*": ["./*"] }, diff --git a/frontend/.eslintrc.js b/frontend/.eslintrc.js index 8f54669c0c..b1d3410458 100644 --- a/frontend/.eslintrc.js +++ b/frontend/.eslintrc.js @@ -6,11 +6,7 @@ module.exports = { es2022: true, }, - extends: [ - 'plugin:vue/vue3-recommended', - '@vue/airbnb', - '@vue/typescript', - ], + extends: ['plugin:vue/vue3-recommended', '@vue/airbnb', '@vue/typescript', 'plugin:storybook/recommended'], parserOptions: { ecmaVersion: 2020, diff --git a/frontend/.storybook/main.js b/frontend/.storybook/main.js new file mode 100644 index 0000000000..813677b88e --- /dev/null +++ b/frontend/.storybook/main.js @@ -0,0 +1,17 @@ +/** @type { import('@storybook/vue3-vite').StorybookConfig } */ +const config = { + stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"], + addons: [ + "@storybook/addon-links", + "@storybook/addon-essentials", + "@storybook/addon-interactions", + ], + framework: { + name: "@storybook/vue3-vite", + options: {}, + }, + docs: { + autodocs: "tag", + }, +}; +export default config; diff --git a/frontend/.storybook/preview.js b/frontend/.storybook/preview.js new file mode 100644 index 0000000000..1dc14d6616 --- /dev/null +++ b/frontend/.storybook/preview.js @@ -0,0 +1,17 @@ +/** @type { import('@storybook/vue3').Preview } */ +import '../src/assets/scss/index.scss'; +import './storybook.scss'; + +const preview = { + parameters: { + actions: { argTypesRegex: "^on[A-Z].*" }, + controls: { + matchers: { + color: /(background|color)$/i, + date: /Date$/i, + }, + }, + }, +}; + +export default preview; diff --git a/frontend/.storybook/storybook.scss b/frontend/.storybook/storybook.scss new file mode 100644 index 0000000000..8f4e445793 --- /dev/null +++ b/frontend/.storybook/storybook.scss @@ -0,0 +1,14 @@ +@import 'https://cdn.jsdelivr.net/npm/remixicon@3.5.0/fonts/remixicon.css'; +@import 'https://fonts.googleapis.com/css2?family=Inter:wght@100;200;300;400;500;600;700;800;900&display=swap'; + +// fixing storybook broken styles because of imported styles +.tag{ + margin-top: initial !important; + margin-bottom: initial !important; + border-radius: initial !important; + border-width: 0 !important; + border-color: initial !important; + background-color: initial !important; + padding: initial !important; + line-height:initial !important; +} diff --git a/frontend/.tailwind/colorConverter.js b/frontend/.tailwind/colorConverter.js new file mode 100644 index 0000000000..1a9870f95e --- /dev/null +++ b/frontend/.tailwind/colorConverter.js @@ -0,0 +1,48 @@ +const fs = require('fs'); +const path = require('path'); + +const colorUtilities = path.resolve(__dirname + '/' + '../config/styles/utilities/_colors.scss') +const colorVariables = path.resolve(__dirname + '/' + '../config/styles/variables/_colors.scss') + +function extractRootVariables(file) { + const scssFile = fs.readFileSync(file, 'utf-8'); // Read the CSS file + + // Regular expression to match CSS variables + const regex = /--(.*?):\s*(.*?);/g; + let match; + const variables = {}; + + // Extract variables + while ((match = regex.exec(scssFile)) !== null) { + variables[`--${match[1].trim()}`] = match[2].trim(); + } + + return variables; +} + +function getThemeReplacementsValues() { + const colorValues = extractRootVariables(colorVariables); + const colorMappings = extractRootVariables(colorUtilities); + + const colorHexes = {...colorValues}; // Clone the first object + for (const key in colorMappings) { + if (colorMappings.hasOwnProperty(key)) { + const varName = colorMappings[key].match(/\(([^)]+)\)/)[1]; // Extract the variable name + if (varName && colorHexes[varName]) { + colorHexes[key] = colorHexes[varName]; // Replace var(--variable) with actual value + } + } + } + return Object.keys(colorHexes) + .reduce((map, key) => { + return { + ...map, + [`var(${key})`]: colorHexes[key] + } + }, {}) +} + +module.exports = { + extractRootVariables, + getThemeReplacementsValues, +}; diff --git a/frontend/Dockerfile.dev b/frontend/Dockerfile.dev index 66b2245552..35f2ab09c7 100644 --- a/frontend/Dockerfile.dev +++ b/frontend/Dockerfile.dev @@ -7,4 +7,6 @@ RUN npm ci COPY .browserslistrc .eslintrc.js babel.config.js postcss.config.js tailwind.config.js vite.config.js tsconfig.json index.html ./ COPY ./public ./public -COPY ./src ./src \ No newline at end of file +COPY ./src ./src +COPY ./.tailwind ./.tailwind +COPY ./config ./config diff --git a/frontend/Dockerfile.kube b/frontend/Dockerfile.kube index 66b63dbc44..2b32ccf441 100644 --- a/frontend/Dockerfile.kube +++ b/frontend/Dockerfile.kube @@ -8,6 +8,8 @@ RUN npm ci COPY .browserslistrc .eslintrc.js babel.config.js postcss.config.js tailwind.config.js vite.config.js tsconfig.json index.html ./ COPY ./public ./public COPY ./src ./src +COPY ./.tailwind ./.tailwind +COPY ./config ./config RUN NODE_ENV=production npm run build:production FROM nginx:1.23-alpine as release @@ -18,4 +20,4 @@ COPY nginx.kube.conf /etc/nginx/nginx.conf COPY ./scripts/docker-entrypoint.sh /docker-entrypoint.sh COPY --from=builder /usr/crowd/frontend/dist /etc/nginx/html -ENTRYPOINT [ "/docker-entrypoint.sh" ] \ No newline at end of file +ENTRYPOINT [ "/docker-entrypoint.sh" ] diff --git a/frontend/config/styles/components/button.scss b/frontend/config/styles/components/button.scss new file mode 100644 index 0000000000..0052556bc7 --- /dev/null +++ b/frontend/config/styles/components/button.scss @@ -0,0 +1,389 @@ +:root { + /* ---------------------------------- *\ + Button sizes + \* ---------------------------------- */ + + /* Tiny */ + --cr-btn-tiny-font-size: #{rem(12)}; + --cr-btn-tiny-line-height: #{rem(20)}; + --cr-btn-tiny-height: #{rem(24)}; + --cr-btn-tiny-border-radius: #{rem(6)}; + --cr-btn-tiny-padding: #{rem(8)}; + --cr-btn-tiny-icon: #{rem(14)}; + + + /* Small */ + --cr-btn-small-font-size: #{rem(13)}; + --cr-btn-small-line-height: #{rem(20)}; + --cr-btn-small-height: #{rem(32)}; + --cr-btn-small-border-radius: #{rem(8)}; + --cr-btn-small-padding: #{rem(12)}; + --cr-btn-small-icon: #{rem(16)}; + + + /* Medium */ + --cr-btn-medium-font-size: #{rem(14)}; + --cr-btn-medium-line-height: #{rem(20)}; + --cr-btn-medium-height: #{rem(40)}; + --cr-btn-medium-border-radius: #{rem(8)}; + --cr-btn-medium-padding: #{rem(16)}; + --cr-btn-medium-icon: #{rem(20)}; + + + /* Large */ + --cr-btn-large-font-size: #{rem(16)}; + --cr-btn-large-line-height: #{rem(20)}; + --cr-btn-large-height: #{rem(48)}; + --cr-btn-large-border-radius: #{rem(10)}; + --cr-btn-large-padding: #{rem(20)}; + --cr-btn-large-icon: #{rem(24)}; + + + /* ---------------------------------- *\ + Button styles + \* ---------------------------------- */ + + /* Primary */ + --cr-btn-primary-text: var(--color-white); + --cr-btn-primary-background: var(--color-gray-900); + --cr-btn-primary-border: var(--color-gray-900); + --cr-btn-primary-shadow: var(--shadow-none); + // Hover + --cr-btn-primary-hover-text: var(--color-white); + --cr-btn-primary-hover-background: var(--color-gray-700); + --cr-btn-primary-hover-border: var(--color-gray-700); + // Active + --cr-btn-primary-active-text: var(--color-white); + --cr-btn-primary-active-background: var(--color-gray-500); + --cr-btn-primary-active-border: var(--color-gray-500); + // Disabled + --cr-btn-primary-disabled-text: var(--color-white); + --cr-btn-primary-disabled-background: var(--color-gray-300); + --cr-btn-primary-disabled-border: var(--color-gray-300); + // Loading + --cr-btn-primary-loading-text: var(--color-gray-400); + --cr-btn-primary-loading-background: var(--color-gray-900); + --cr-btn-primary-loading-border: var(--color-gray-900); + + + /* Secondary */ + --cr-btn-secondary-text: var(--color-gray-900); + --cr-btn-secondary-background: var(--color-white); + --cr-btn-secondary-border: var(--color-gray-100); + --cr-btn-secondary-shadow: var(--shadow-default); + // Hover + --cr-btn-secondary-hover-text: var(--color-gray-900); + --cr-btn-secondary-hover-background: var(--color-gray-50); + --cr-btn-secondary-hover-border: var(--color-gray-100); + // Active + --cr-btn-secondary-active-text: var(--color-gray-900); + --cr-btn-secondary-active-background: var(--color-gray-100); + --cr-btn-secondary-active-border: var(--color-gray-100); + // Disabled + --cr-btn-secondary-disabled-text: var(--color-gray-300); + --cr-btn-secondary-disabled-background: var(--color-white); + --cr-btn-secondary-disabled-border: var(--color-gray-100); + // Loading + --cr-btn-secondary-loading-text: var(--color-gray-400); + --cr-btn-secondary-loading-background: var(--color-white); + --cr-btn-secondary-loading-border: var(--color-gray-100); + + + /* Tertiary */ + --cr-btn-tertiary-text: var(--color-brand-500); + --cr-btn-tertiary-background: var(--color-transparent); + --cr-btn-tertiary-border: var(--color-transparent); + --cr-btn-tertiary-shadow: var(--shadow-none); + // Hover + --cr-btn-tertiary-hover-text: var(--color-brand-500); + --cr-btn-tertiary-hover-background: var(--color-brand-50); + --cr-btn-tertiary-hover-border: var(--color-brand-50); + // Active + --cr-btn-tertiary-active-text: var(--color-brand-500); + --cr-btn-tertiary-active-background: var(--color-brand-100); + --cr-btn-tertiary-active-border: var(--color-brand-100); + // Disabled + --cr-btn-tertiary-disabled-text: var(--color-brand-200); + --cr-btn-tertiary-disabled-background: var(--color-transparent); + --cr-btn-tertiary-disabled-border: var(--color-transparent); + // Loading + --cr-btn-tertiary-loading-text: var(--color-brand-300); + --cr-btn-tertiary-loading-background: var(--color-transparent); + --cr-btn-tertiary-loading-border: var(--color-transparent); + + + /* Tertiary Gray */ + --cr-btn-tertiary-gray-text: var(--color-gray-600); + --cr-btn-tertiary-gray-background: var(--color-transparent); + --cr-btn-tertiary-gray-border: var(--color-transparent); + --cr-btn-tertiary-gray-shadow: var(--shadow-none); + // Hover + --cr-btn-tertiary-gray-hover-text: var(--color-gray-600); + --cr-btn-tertiary-gray-hover-background: var(--color-gray-100); + --cr-btn-tertiary-gray-hover-border: var(--color-gray-100); + // Active + --cr-btn-tertiary-gray-active-text: var(--color-gray-600); + --cr-btn-tertiary-gray-active-background: var(--color-gray-200); + --cr-btn-tertiary-gray-active-border: var(--color-gray-200); + // Disabled + --cr-btn-tertiary-gray-disabled-text: var(--color-gray-300); + --cr-btn-tertiary-gray-disabled-background: var(--color-transparent); + --cr-btn-tertiary-gray-disabled-border: var(--color-transparent); + // Loading + --cr-btn-tertiary-gray-loading-text: var(--color-gray-400); + --cr-btn-tertiary-gray-loading-background: var(--color-transparent); + --cr-btn-tertiary-gray-loading-border: var(--color-transparent); + + + /* Tertiary Light Gray */ + --cr-btn-tertiary-light-gray-text: var(--color-gray-400); + --cr-btn-tertiary-light-gray-background: var(--color-transparent); + --cr-btn-tertiary-light-gray-border: var(--color-transparent); + --cr-btn-tertiary-light-gray-shadow: var(--shadow-none); + // Hover + --cr-btn-tertiary-light-gray-hover-text: var(--color-gray-500); + --cr-btn-tertiary-light-gray-hover-background: var(--color-gray-50); + --cr-btn-tertiary-light-gray-hover-border: var(--color-gray-50); + // Active + --cr-btn-tertiary-light-gray-active-text: var(--color-gray-500); + --cr-btn-tertiary-light-gray-active-background: var(--color-gray-100); + --cr-btn-tertiary-light-gray-active-border: var(--color-gray-100); + // Disabled + --cr-btn-tertiary-light-gray-disabled-text: var(--color-gray-300); + --cr-btn-tertiary-light-gray-disabled-background: var(--color-transparent); + --cr-btn-tertiary-light-gray-disabled-border: var(--color-transparent); + // Loading + --cr-btn-tertiary-light-gray-loading-text: var(--color-gray-300); + --cr-btn-tertiary-light-gray-loading-background: var(--color-transparent); + --cr-btn-tertiary-light-gray-loading-border: var(--color-transparent); + + + /* Info */ + --cr-btn-info-text: var(--color-white); + --cr-btn-info-background: var(--color-blue-600); + --cr-btn-info-border: var(--color-blue-600); + --cr-btn-info-shadow: var(--shadow-none); + // Hover + --cr-btn-info-hover-text: var(--color-white); + --cr-btn-info-hover-background: var(--color-blue-700); + --cr-btn-info-hover-border: var(--color-blue-700); + // Active + --cr-btn-info-active-text: var(--color-white); + --cr-btn-info-active-background: var(--color-blue-800); + --cr-btn-info-active-border: var(--color-blue-800); + // Disabled + --cr-btn-info-disabled-text: var(--color-white); + --cr-btn-info-disabled-background: var(--color-blue-300); + --cr-btn-info-disabled-border: var(--color-blue-300); + // Loading + --cr-btn-info-loading-text: var(--color-blue-200); + --cr-btn-info-loading-background: var(--color-blue-600); + --cr-btn-info-loading-border: var(--color-blue-600); + + + /* Info Transparent */ + --cr-btn-info-transparent-text: var(--color-blue-600); + --cr-btn-info-transparent-background: var(--color-transparent); + --cr-btn-info-transparent-border: var(--color-transparent); + --cr-btn-info-transparent-shadow: var(--shadow-none); + // Hover + --cr-btn-info-transparent-hover-text: var(--color-blue-600); + --cr-btn-info-transparent-hover-background: var(--color-blue-50); + --cr-btn-info-transparent-hover-border: var(--color-blue-50); + // Active + --cr-btn-info-transparent-active-text: var(--color-blue-600); + --cr-btn-info-transparent-active-background: var(--color-blue-100); + --cr-btn-info-transparent-active-border: var(--color-blue-100); + // Disabled + --cr-btn-info-transparent-disabled-text: var(--color-blue-300); + --cr-btn-info-transparent-disabled-background: var(--color-transparent); + --cr-btn-info-transparent-disabled-border: var(--color-transparent); + // Loading + --cr-btn-info-transparent-loading-text: var(--color-blue-400); + --cr-btn-info-transparent-loading-background: var(--color-transparent); + --cr-btn-info-transparent-loading-border: var(--color-transparent); + + + /* Success */ + --cr-btn-success-text: var(--color-white); + --cr-btn-success-background: var(--color-green-600); + --cr-btn-success-border: var(--color-green-600); + --cr-btn-success-shadow: var(--shadow-none); + // Hover + --cr-btn-success-hover-text: var(--color-white); + --cr-btn-success-hover-background: var(--color-green-700); + --cr-btn-success-hover-border: var(--color-green-700); + // Active + --cr-btn-success-active-text: var(--color-white); + --cr-btn-success-active-background: var(--color-green-800); + --cr-btn-success-active-border: var(--color-green-800); + // Disabled + --cr-btn-success-disabled-text: var(--color-white); + --cr-btn-success-disabled-background: var(--color-green-300); + --cr-btn-success-disabled-border: var(--color-green-300); + // Loading + --cr-btn-success-loading-text: var(--color-green-200); + --cr-btn-success-loading-background: var(--color-green-600); + --cr-btn-success-loading-border: var(--color-green-600); + + + /* Success Transparent */ + --cr-btn-success-transparent-text: var(--color-green-600); + --cr-btn-success-transparent-background: var(--color-transparent); + --cr-btn-success-transparent-border: var(--color-transparent); + --cr-btn-success-transparent-shadow: var(--shadow-none); + // Hover + --cr-btn-success-transparent-hover-text: var(--color-green-600); + --cr-btn-success-transparent-hover-background: var(--color-green-50); + --cr-btn-success-transparent-hover-border: var(--color-green-50); + // Active + --cr-btn-success-transparent-active-text: var(--color-green-600); + --cr-btn-success-transparent-active-background: var(--color-green-100); + --cr-btn-success-transparent-active-border: var(--color-green-100); + // Disabled + --cr-btn-success-transparent-disabled-text: var(--color-green-300); + --cr-btn-success-transparent-disabled-background: var(--color-transparent); + --cr-btn-success-transparent-disabled-border: var(--color-transparent); + // Loading + --cr-btn-success-transparent-loading-text: var(--color-green-400); + --cr-btn-success-transparent-loading-background: var(--color-transparent); + --cr-btn-success-transparent-loading-border: var(--color-transparent); + + + /* Danger */ + --cr-btn-danger-text: var(--color-white); + --cr-btn-danger-background: var(--color-red-600); + --cr-btn-danger-border: var(--color-red-600); + --cr-btn-danger-shadow: var(--shadow-none); + // Hover + --cr-btn-danger-hover-text: var(--color-white); + --cr-btn-danger-hover-background: var(--color-red-700); + --cr-btn-danger-hover-border: var(--color-red-700); + // Active + --cr-btn-danger-active-text: var(--color-white); + --cr-btn-danger-active-background: var(--color-red-800); + --cr-btn-danger-active-border: var(--color-red-800); + // Disabled + --cr-btn-danger-disabled-text: var(--color-white); + --cr-btn-danger-disabled-background: var(--color-red-300); + --cr-btn-danger-disabled-border: var(--color-red-300); + // Loading + --cr-btn-danger-loading-text: var(--color-red-200); + --cr-btn-danger-loading-background: var(--color-red-600); + --cr-btn-danger-loading-border: var(--color-red-600); + + + /* Danger Transparent */ + --cr-btn-danger-transparent-text: var(--color-red-600); + --cr-btn-danger-transparent-background: var(--color-transparent); + --cr-btn-danger-transparent-border: var(--color-transparent); + --cr-btn-danger-transparent-shadow: var(--shadow-none); + // Hover + --cr-btn-danger-transparent-hover-text: var(--color-red-600); + --cr-btn-danger-transparent-hover-background: var(--color-red-50); + --cr-btn-danger-transparent-hover-border: var(--color-red-50); + // Active + --cr-btn-danger-transparent-active-text: var(--color-red-600); + --cr-btn-danger-transparent-active-background: var(--color-red-100); + --cr-btn-danger-transparent-active-border: var(--color-red-100); + // Disabled + --cr-btn-danger-transparent-disabled-text: var(--color-red-300); + --cr-btn-danger-transparent-disabled-background: var(--color-transparent); + --cr-btn-danger-transparent-disabled-border: var(--color-transparent); + // Loading + --cr-btn-danger-transparent-loading-text: var(--color-red-400); + --cr-btn-danger-transparent-loading-background: var(--color-transparent); + --cr-btn-danger-transparent-loading-border: var(--color-transparent); + + + /* Warning */ + --cr-btn-warning-text: var(--color-white); + --cr-btn-warning-background: var(--color-yellow-500); + --cr-btn-warning-border: var(--color-yellow-500); + --cr-btn-warning-shadow: var(--shadow-none); + // Hover + --cr-btn-warning-hover-text: var(--color-white); + --cr-btn-warning-hover-background: var(--color-yellow-600); + --cr-btn-warning-hover-border: var(--color-yellow-600); + // Active + --cr-btn-warning-active-text: var(--color-white); + --cr-btn-warning-active-background: var(--color-yellow-700); + --cr-btn-warning-active-border: var(--color-yellow-700); + // Disabled + --cr-btn-warning-disabled-text: var(--color-white); + --cr-btn-warning-disabled-background: var(--color-yellow-300); + --cr-btn-warning-disabled-border: var(--color-yellow-300); + // Loading + --cr-btn-warning-loading-text: var(--color-yellow-200); + --cr-btn-warning-loading-background: var(--color-yellow-500); + --cr-btn-warning-loading-border: var(--color-yellow-500); + + + /* Warning Transparent */ + --cr-btn-warning-transparent-text: var(--color-yellow-500); + --cr-btn-warning-transparent-background: var(--color-transparent); + --cr-btn-warning-transparent-border: var(--color-transparent); + --cr-btn-warning-transparent-shadow: var(--shadow-none); + // Hover + --cr-btn-warning-transparent-hover-text: var(--color-yellow-500); + --cr-btn-warning-transparent-hover-background: var(--color-yellow-50); + --cr-btn-warning-transparent-hover-border: var(--color-yellow-50); + // Active + --cr-btn-warning-transparent-active-text: var(--color-yellow-500); + --cr-btn-warning-transparent-active-background: var(--color-yellow-100); + --cr-btn-warning-transparent-active-border: var(--color-yellow-100); + // Disabled + --cr-btn-warning-transparent-disabled-text: var(--color-yellow-300); + --cr-btn-warning-transparent-disabled-background: var(--color-transparent); + --cr-btn-warning-transparent-disabled-border: var(--color-transparent); + // Loading + --cr-btn-warning-transparent-loading-text: var(--color-yellow-400); + --cr-btn-warning-transparent-loading-background: var(--color-transparent); + --cr-btn-warning-transparent-loading-border: var(--color-transparent); + + + /* Feature */ + --cr-btn-feature-text: var(--color-white); + --cr-btn-feature-background: var(--color-purple-600); + --cr-btn-feature-border: var(--color-purple-600); + --cr-btn-feature-shadow: var(--shadow-none); + // Hover + --cr-btn-feature-hover-text: var(--color-white); + --cr-btn-feature-hover-background: var(--color-purple-700); + --cr-btn-feature-hover-border: var(--color-purple-700); + // Active + --cr-btn-feature-active-text: var(--color-white); + --cr-btn-feature-active-background: var(--color-purple-800); + --cr-btn-feature-active-border: var(--color-purple-800); + // Disabled + --cr-btn-feature-disabled-text: var(--color-white); + --cr-btn-feature-disabled-background: var(--color-purple-300); + --cr-btn-feature-disabled-border: var(--color-purple-300); + // Loading + --cr-btn-feature-loading-text: var(--color-purple-200); + --cr-btn-feature-loading-background: var(--color-purple-600); + --cr-btn-feature-loading-border: var(--color-purple-600); + + + /* Feature Transparent */ + --cr-btn-feature-transparent-text: var(--color-purple-600); + --cr-btn-feature-transparent-background: var(--color-transparent); + --cr-btn-feature-transparent-border: var(--color-transparent); + --cr-btn-feature-transparent-shadow: var(--shadow-none); + // Hover + --cr-btn-feature-transparent-hover-text: var(--color-purple-600); + --cr-btn-feature-transparent-hover-background: var(--color-purple-50); + --cr-btn-feature-transparent-hover-border: var(--color-purple-50); + // Active + --cr-btn-feature-transparent-active-text: var(--color-purple-600); + --cr-btn-feature-transparent-active-background: var(--color-purple-100); + --cr-btn-feature-transparent-active-border: var(--color-purple-100); + // Disabled + --cr-btn-feature-transparent-disabled-text: var(--color-purple-300); + --cr-btn-feature-transparent-disabled-background: var(--color-transparent); + --cr-btn-feature-transparent-disabled-border: var(--color-transparent); + // Loading + --cr-btn-feature-transparent-loading-text: var(--color-purple-400); + --cr-btn-feature-transparent-loading-background: var(--color-transparent); + --cr-btn-feature-transparent-loading-border: var(--color-transparent); +} diff --git a/frontend/config/styles/components/card.scss b/frontend/config/styles/components/card.scss new file mode 100644 index 0000000000..5636619bae --- /dev/null +++ b/frontend/config/styles/components/card.scss @@ -0,0 +1,10 @@ +:root { + /* ---------------------------------- *\ + Card style + \* ---------------------------------- */ + + --cr-card-shadow: var(--shadow-default); + --cr-card-radius: #{rem(8)}; + --cr-card-background: var(--color-white); + --cr-card-border: none; +} diff --git a/frontend/config/styles/components/checkbox.scss b/frontend/config/styles/components/checkbox.scss new file mode 100644 index 0000000000..25498573a4 --- /dev/null +++ b/frontend/config/styles/components/checkbox.scss @@ -0,0 +1,54 @@ +:root { + /* ---------------------------------- *\ + Checkbox style + \* ---------------------------------- */ + + // General style + --cr-checkbox-shadow: var(--shadow-s); + --cr-checkbox-border-radius: #{rem(4)}; + + // Text style + --cr-checkbox-text-font-weight: var(--font-medium); + --cr-checkbox-text-color: var(--color-gray-900); + + // Description style + --cr-checkbox-description-font-size: #{rem(12)}; + --cr-checkbox-description-line-height: #{rem(15)}; + --cr-checkbox-description-font-weight: var(--font-normal); + --cr-checkbox-description-color: var(--color-gray-500); + --cr-checkbox-description-spacing: #{rem(4)}; + + // Unchecked + --cr-checkbox-unchecked-border: var(--color-gray-300); + --cr-checkbox-unchecked-background: var(--color-white); + --cr-checkbox-unchecked-icon: var(--color-white); + + // Checked + --cr-checkbox-checked-border: var(--color-gray-900); + --cr-checkbox-checked-background: var(--color-gray-900); + --cr-checkbox-checked-icon: var(--color-white); + + // Disabled Unchecked + --cr-checkbox-disabled-unchecked-border: var(--color-gray-200); + --cr-checkbox-disabled-unchecked-background: var(--color-white); + --cr-checkbox-disabled-unchecked-icon: var(--color-white); + + // Disabled Checked + --cr-checkbox-disabled-checked-border: var(--color-gray-400); + --cr-checkbox-disabled-checked-background: var(--color-gray-400); + --cr-checkbox-disabled-checked-icon: var(--color-white); + + /* ---------------------------------- *\ + Checkbox sizes + \* ---------------------------------- */ + + /* Small */ + --cr-checkbox-small-size: #{rem(14)}; + --cr-checkbox-small-font-size: #{rem(13)}; + --cr-checkbox-small-line-height: 1.25; + + /* Medium */ + --cr-checkbox-medium-size: #{rem(16)}; + --cr-checkbox-medium-font-size: #{rem(14)}; + --cr-checkbox-medium-line-height: 1.25; +} diff --git a/frontend/config/styles/components/index.scss b/frontend/config/styles/components/index.scss new file mode 100644 index 0000000000..802b98b11b --- /dev/null +++ b/frontend/config/styles/components/index.scss @@ -0,0 +1,3 @@ +@import "button"; +@import "card"; +@import "checkbox"; diff --git a/frontend/config/styles/index.scss b/frontend/config/styles/index.scss new file mode 100644 index 0000000000..1e15f40a73 --- /dev/null +++ b/frontend/config/styles/index.scss @@ -0,0 +1,3 @@ +@import 'variables'; +@import 'utilities'; +@import 'components'; diff --git a/frontend/config/styles/utilities/_colors.scss b/frontend/config/styles/utilities/_colors.scss new file mode 100755 index 0000000000..af598859f0 --- /dev/null +++ b/frontend/config/styles/utilities/_colors.scss @@ -0,0 +1,134 @@ +/* ---------------------------------- *\ + Colors +\* ---------------------------------- */ + +:root { + // Main colors + --cr-color-transparent: var(--color-transparent); + --cr-color-white: var(--color-white); + --cr-color-black: var(--color-black); + --cr-color-background: var(--color-background); + + // Brand + --cr-color-brand-900: var(--color-brand-900); + --cr-color-brand-800: var(--color-brand-800); + --cr-color-brand-700: var(--color-brand-700); + --cr-color-brand-600: var(--color-brand-600); + --cr-color-brand-500: var(--color-brand-500); + --cr-color-brand-400: var(--color-brand-400); + --cr-color-brand-300: var(--color-brand-300); + --cr-color-brand-200: var(--color-brand-200); + --cr-color-brand-100: var(--color-brand-100); + --cr-color-brand-50: var(--color-brand-50); + --cr-color-brand-25: var(--color-brand-25); + + // Gray + --cr-color-gray-1000: var(--color-gray-1000); + --cr-color-gray-900: var(--color-gray-900); + --cr-color-gray-800: var(--color-gray-800); + --cr-color-gray-700: var(--color-gray-700); + --cr-color-gray-600: var(--color-gray-600); + --cr-color-gray-500: var(--color-gray-500); + --cr-color-gray-400: var(--color-gray-400); + --cr-color-gray-300: var(--color-gray-300); + --cr-color-gray-200: var(--color-gray-200); + --cr-color-gray-100: var(--color-gray-100); + --cr-color-gray-50: var(--color-gray-50); + + // Blue + --cr-color-blue-900: var(--color-blue-900); + --cr-color-blue-800: var(--color-blue-800); + --cr-color-blue-700: var(--color-blue-700); + --cr-color-blue-600: var(--color-blue-600); + --cr-color-blue-500: var(--color-blue-500); + --cr-color-blue-400: var(--color-blue-400); + --cr-color-blue-300: var(--color-blue-300); + --cr-color-blue-200: var(--color-blue-200); + --cr-color-blue-100: var(--color-blue-100); + --cr-color-blue-50: var(--color-blue-50); + + // Red + --cr-color-red-900: var(--color-red-900); + --cr-color-red-800: var(--color-red-800); + --cr-color-red-700: var(--color-red-700); + --cr-color-red-600: var(--color-red-600); + --cr-color-red-500: var(--color-red-500); + --cr-color-red-400: var(--color-red-400); + --cr-color-red-300: var(--color-red-300); + --cr-color-red-200: var(--color-red-200); + --cr-color-red-100: var(--color-red-100); + --cr-color-red-50: var(--color-red-50); + + // Yellow + --cr-color-yellow-900: var(--color-yellow-900); + --cr-color-yellow-800: var(--color-yellow-800); + --cr-color-yellow-700: var(--color-yellow-700); + --cr-color-yellow-600: var(--color-yellow-600); + --cr-color-yellow-500: var(--color-yellow-500); + --cr-color-yellow-400: var(--color-yellow-400); + --cr-color-yellow-300: var(--color-yellow-300); + --cr-color-yellow-200: var(--color-yellow-200); + --cr-color-yellow-100: var(--color-yellow-100); + --cr-color-yellow-50: var(--color-yellow-50); + + // Green + --cr-color-green-1000: var(--color-green-1000); + --cr-color-green-900: var(--color-green-900); + --cr-color-green-800: var(--color-green-800); + --cr-color-green-700: var(--color-green-700); + --cr-color-green-600: var(--color-green-600); + --cr-color-green-500: var(--color-green-500); + --cr-color-green-400: var(--color-green-400); + --cr-color-green-300: var(--color-green-300); + --cr-color-green-200: var(--color-green-200); + --cr-color-green-100: var(--color-green-100); + --cr-color-green-50: var(--color-green-50); + + // Teal + --cr-color-teal-900: var(--color-teal-900); + --cr-color-teal-800: var(--color-teal-800); + --cr-color-teal-700: var(--color-teal-700); + --cr-color-teal-600: var(--color-teal-600); + --cr-color-teal-500: var(--color-teal-500); + --cr-color-teal-400: var(--color-teal-400); + --cr-color-teal-300: var(--color-teal-300); + --cr-color-teal-200: var(--color-teal-200); + --cr-color-teal-100: var(--color-teal-100); + --cr-color-teal-50: var(--color-teal-50); + + // Purple + --cr-color-purple-900: var(--color-purple-900); + --cr-color-purple-800: var(--color-purple-800); + --cr-color-purple-700: var(--color-purple-700); + --cr-color-purple-600: var(--color-purple-600); + --cr-color-purple-500: var(--color-purple-500); + --cr-color-purple-400: var(--color-purple-400); + --cr-color-purple-300: var(--color-purple-300); + --cr-color-purple-200: var(--color-purple-200); + --cr-color-purple-100: var(--color-purple-100); + --cr-color-purple-50: var(--color-purple-50); + + // Cyan + --cr-color-cyan-900: var(--color-cyan-900); + --cr-color-cyan-800: var(--color-cyan-800); + --cr-color-cyan-700: var(--color-cyan-700); + --cr-color-cyan-600: var(--color-cyan-600); + --cr-color-cyan-500: var(--color-cyan-500); + --cr-color-cyan-400: var(--color-cyan-400); + --cr-color-cyan-300: var(--color-cyan-300); + --cr-color-cyan-200: var(--color-cyan-200); + --cr-color-cyan-100: var(--color-cyan-100); + --cr-color-cyan-50: var(--color-cyan-50); + + // Orange + --cr-color-orange-900: var(--color-orange-900); + --cr-color-orange-800: var(--color-orange-800); + --cr-color-orange-700: var(--color-orange-700); + --cr-color-orange-600: var(--color-orange-600); + --cr-color-orange-500: var(--color-orange-500); + --cr-color-orange-400: var(--color-orange-400); + --cr-color-orange-300: var(--color-orange-300); + --cr-color-orange-200: var(--color-orange-200); + --cr-color-orange-100: var(--color-orange-100); + --cr-color-orange-50: var(--color-orange-50); +} diff --git a/frontend/config/styles/utilities/index.scss b/frontend/config/styles/utilities/index.scss new file mode 100644 index 0000000000..32f1c45109 --- /dev/null +++ b/frontend/config/styles/utilities/index.scss @@ -0,0 +1 @@ +@import "colors"; diff --git a/frontend/config/styles/variables/_colors.scss b/frontend/config/styles/variables/_colors.scss new file mode 100755 index 0000000000..687580a231 --- /dev/null +++ b/frontend/config/styles/variables/_colors.scss @@ -0,0 +1,134 @@ +/* ---------------------------------- *\ + Colors +\* ---------------------------------- */ + +:root { + // Main colors + --color-transparent: transparent; + --color-white: #fff; + --color-black: #140505; + --color-background: #f8f8f8; + + // Brand + --color-brand-900: #2F1009; + --color-brand-800: #5D2012; + --color-brand-700: #8C2F1C; + --color-brand-600: #BA3F25; + --color-brand-500: #E94F2E; + --color-brand-400: #ED7258; + --color-brand-300: #F29582; + --color-brand-200: #F6B9AB; + --color-brand-100: #FBDCD5; + --color-brand-50: #FDEDEA; + --color-brand-25: #FDF6F4; + + // Gray + --color-gray-1000: #000000; + --color-gray-900: #111827; + --color-gray-800: #1F2937; + --color-gray-700: #374151; + --color-gray-600: #4B5563; + --color-gray-500: #6B7280; + --color-gray-400: #9CA3AF; + --color-gray-300: #D1D5DB; + --color-gray-200: #E5E7EB; + --color-gray-100: #F3F4F6; + --color-gray-50: #F9FAFB; + + // Blue + --color-blue-900: #1E3A8A; + --color-blue-800: #1E40AF; + --color-blue-700: #1D4ED8; + --color-blue-600: #2563EB; + --color-blue-500: #3B82F6; + --color-blue-400: #60A5FA; + --color-blue-300: #93C5FD; + --color-blue-200: #BFDBFE; + --color-blue-100: #DBEAFE; + --color-blue-50: #EFF6FF; + + // Red + --color-red-900: #7F1D1D; + --color-red-800: #991B1B; + --color-red-700: #B91C1C; + --color-red-600: #DC2626; + --color-red-500: #EF4444; + --color-red-400: #F87171; + --color-red-300: #FCA5A5; + --color-red-200: #FECACA; + --color-red-100: #FEE2E2; + --color-red-50: #FEF2F2; + + // Yellow + --color-yellow-900: #78350F; + --color-yellow-800: #92400E; + --color-yellow-700: #B45309; + --color-yellow-600: #D97706; + --color-yellow-500: #F59E0B; + --color-yellow-400: #FBBF24; + --color-yellow-300: #FCD34D; + --color-yellow-200: #FDE68A; + --color-yellow-100: #FEF3C7; + --color-yellow-50: #FFFBEB; + + // Green + --color-green-1000: #059669; + --color-green-900: #14532D; + --color-green-800: #166534; + --color-green-700: #15803D; + --color-green-600: #16A34A; + --color-green-500: #10B981; + --color-green-400: #4ADE80; + --color-green-300: #86EFAC; + --color-green-200: #BBF7D0; + --color-green-100: #DCFCE7; + --color-green-50: #F0FDF4; + + // Teal + --color-teal-900: #134E4A; + --color-teal-800: #115E59; + --color-teal-700: #0F766E; + --color-teal-600: #0D9488; + --color-teal-500: #14B8A6; + --color-teal-400: #2DD4BF; + --color-teal-300: #5EEAD4; + --color-teal-200: #99F6E4; + --color-teal-100: #CCFBF1; + --color-teal-50: #F0FDFA; + + // Purple + --color-purple-900: #4C1D95; + --color-purple-800: #5B21B6; + --color-purple-700: #6D28D9; + --color-purple-600: #7C3AED; + --color-purple-500: #8B5CF6; + --color-purple-400: #A78BFA; + --color-purple-300: #C4B5FD; + --color-purple-200: #DDD6FE; + --color-purple-100: #EDE9FE; + --color-purple-50: #F5F3FF; + + // Cyan + --color-cyan-900: #164E63; + --color-cyan-800: #155E75; + --color-cyan-700: #0E7490; + --color-cyan-600: #0891B2; + --color-cyan-500: #06B6D4; + --color-cyan-400: #22D3EE; + --color-cyan-300: #67E8F9; + --color-cyan-200: #A5F3FC; + --color-cyan-100: #CFFAFE; + --color-cyan-50: #ECFEFF; + + // Orange + --color-orange-900: #7C2D12; + --color-orange-800: #9A3412; + --color-orange-700: #C2410C; + --color-orange-600: #EA580C; + --color-orange-500: #F97316; + --color-orange-400: #FB923C; + --color-orange-300: #FDBA74; + --color-orange-200: #FED7AA; + --color-orange-100: #FFEDD5; + --color-orange-50: #FFF7ED; +} diff --git a/frontend/config/styles/variables/_font.scss b/frontend/config/styles/variables/_font.scss new file mode 100755 index 0000000000..2337253cf4 --- /dev/null +++ b/frontend/config/styles/variables/_font.scss @@ -0,0 +1,10 @@ +/* ---------------------------------- *\ + Font +\* ---------------------------------- */ + +:root { + --font-light: 300; + --font-normal: 400; + --font-medium: 500; + --font-bold: 700; +} diff --git a/frontend/config/styles/variables/_shadows.scss b/frontend/config/styles/variables/_shadows.scss new file mode 100755 index 0000000000..07fa3d2d16 --- /dev/null +++ b/frontend/config/styles/variables/_shadows.scss @@ -0,0 +1,13 @@ +/* ---------------------------------- *\ + Colors +\* ---------------------------------- */ + +:root { + // Shadows + --shadow-none: none; + --shadow-s: 0px 1px 2px 0px rgba(0, 0, 0, 0.05); + --shadow-default: 0px 1px 3px 0px rgba(0, 0, 0, 0.10), 0px 1px 2px -1px rgba(0, 0, 0, 0.10);; + --shadow-m: 0px 4px 6px -1px rgba(0, 0, 0, 0.10), 0px 2px 4px -2px rgba(0, 0, 0, 0.10);; + --shadow-l: 0px 10px 15px -3px rgba(0, 0, 0, 0.10), 0px 4px 6px -4px rgba(0, 0, 0, 0.10);; + --shadow-xl: 0px 20px 25px -5px rgba(0, 0, 0, 0.10), 0px 8px 10px -6px rgba(0, 0, 0, 0.10);; +} diff --git a/frontend/config/styles/variables/index.scss b/frontend/config/styles/variables/index.scss new file mode 100644 index 0000000000..7562c47c87 --- /dev/null +++ b/frontend/config/styles/variables/index.scss @@ -0,0 +1,3 @@ +@import "colors"; +@import "font"; +@import "shadows"; diff --git a/frontend/package-lock.json b/frontend/package-lock.json index f9297e73ac..3c80478bcd 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -62,7 +62,15 @@ "yup": "^0.32.11" }, "devDependencies": { + "@storybook/addon-essentials": "^7.6.10", + "@storybook/addon-interactions": "^7.6.10", + "@storybook/addon-links": "^7.6.10", + "@storybook/blocks": "^7.6.10", + "@storybook/test": "^7.6.10", + "@storybook/vue3": "^7.6.10", + "@storybook/vue3-vite": "^7.6.10", "@tailwindcss/line-clamp": "^0.4.2", + "@types/pluralize": "^0.0.33", "@typescript-eslint/eslint-plugin": "^5.4.0", "@typescript-eslint/parser": "^5.4.0", "@vue/compiler-sfc": "^3.2.29", @@ -75,11 +83,15 @@ "dotenv": "^16.0.3", "eslint": "^8.36.0", "eslint-plugin-cypress": "^2.12.1", + "eslint-plugin-storybook": "^0.6.15", "eslint-plugin-vue": "^9.10.0", "mini-css-extract-plugin": "^2.7.5", "postcss": "^8.4.21", + "react": "^18.2.0", + "react-dom": "^18.2.0", "rollup-plugin-visualizer": "^5.9.2", "sass": "^1.60.0", + "storybook": "^7.6.10", "tailwind-config-viewer": "^1.7.2", "tailwindcss": "^3.2.7", "terser-webpack-plugin": "^5.3.7", @@ -89,6 +101,12 @@ "wait-on": "^6.0.1" } }, + "node_modules/@adobe/css-tools": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.3.3.tgz", + "integrity": "sha512-rE0Pygv0sEZ4vBWHlAgJLGDU7Pm8xoO6p3wsEceb7GYAjScrOHpEo8KK/eVkAcnSM+slAEtXjA2JpdjLp4fJQQ==", + "dev": true + }, "node_modules/@ampproject/remapping": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", @@ -110,45 +128,58 @@ "url": "https://github.com/sponsors/antfu" } }, + "node_modules/@aw-web-design/x-default-browser": { + "version": "1.4.126", + "resolved": "https://registry.npmjs.org/@aw-web-design/x-default-browser/-/x-default-browser-1.4.126.tgz", + "integrity": "sha512-Xk1sIhyNC/esHGGVjL/niHLowM0csl/kFO5uawBy4IrWwy0o1G8LGt3jP6nmWGz+USxeeqbihAmp/oVZju6wug==", + "dev": true, + "dependencies": { + "default-browser-id": "3.0.0" + }, + "bin": { + "x-default-browser": "bin/x-default-browser.js" + } + }, "node_modules/@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", "dependencies": { - "@babel/highlight": "^7.18.6" + "@babel/highlight": "^7.23.4", + "chalk": "^2.4.2" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.0.tgz", - "integrity": "sha512-gMuZsmsgxk/ENC3O/fRw5QY8A9/uxQbbCEypnLIiYYc/qVJtEV7ouxC3EllIIwNzMqAQee5tanFabWsUOutS7g==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", + "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.3.tgz", - "integrity": "sha512-qIJONzoa/qiHghnm0l1n4i/6IIziDpzqc36FBs4pzMhDUraHqponwJLiAKm1hGLP3OSB/TVNz6rMwVGpwxxySw==", + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.7.tgz", + "integrity": "sha512-+UpDgowcmqe36d4NwqvKsyPMlOLNGMsfMmQ5WGCu+siCe3t3dfe9njrzGfdN4qq+bcNUt0+Vw6haRxBOycs4dw==", "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.21.3", - "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-module-transforms": "^7.21.2", - "@babel/helpers": "^7.21.0", - "@babel/parser": "^7.21.3", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.3", - "@babel/types": "^7.21.3", - "convert-source-map": "^1.7.0", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helpers": "^7.23.7", + "@babel/parser": "^7.23.6", + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.7", + "@babel/types": "^7.23.6", + "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.2.2", - "semver": "^6.3.0" + "json5": "^2.2.3", + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" @@ -159,11 +190,11 @@ } }, "node_modules/@babel/generator": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.3.tgz", - "integrity": "sha512-QS3iR1GYC/YGUnW7IdggFeN5c1poPUurnGttOV/bZgPGV+izC/D8HnD6DLwod0fsatNyVn1G3EVWMYIF0nHbeA==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", + "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", "dependencies": { - "@babel/types": "^7.21.3", + "@babel/types": "^7.23.6", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -185,16 +216,77 @@ "node": ">=6.0.0" } }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", + "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz", + "integrity": "sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz", - "integrity": "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", + "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", "dependencies": { - "@babel/compat-data": "^7.20.5", - "@babel/helper-validator-option": "^7.18.6", - "browserslist": "^4.21.3", + "@babel/compat-data": "^7.23.5", + "@babel/helper-validator-option": "^7.23.5", + "browserslist": "^4.22.2", "lru-cache": "^5.1.1", - "semver": "^6.3.0" + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.23.7.tgz", + "integrity": "sha512-xCoqR/8+BoNnXOY7RVSgv6X+o7pmT5q1d+gGcRlXYkI+9B31glE4jeejhKVpA04O1AtzOt7OSQ6VYKP5FcRl9g==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-member-expression-to-functions": "^7.23.0", + "@babel/helper-optimise-call-expression": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.20", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz", + "integrity": "sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "regexpu-core": "^5.3.1", + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" @@ -203,140 +295,240 @@ "@babel/core": "^7.0.0" } }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.5.0.tgz", + "integrity": "sha512-NovQquuQLAQ5HuyjCz7WQP9MjRj7dx++yspwiyUiGl9ZyadHRSql1HZh5ogRd8W8w6YM6EQ/NTB8rgjLt5W65Q==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", - "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz", - "integrity": "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", "dependencies": { - "@babel/template": "^7.20.7", - "@babel/types": "^7.21.0" + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-hoist-variables": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz", + "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==", + "dev": true, "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.23.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", - "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.15" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.21.2", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz", - "integrity": "sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz", + "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==", + "dev": true, "dependencies": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-simple-access": "^7.20.2", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/helper-validator-identifier": "^7.19.1", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.2", - "@babel/types": "^7.21.2" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz", - "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz", + "integrity": "sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-wrap-function": "^7.22.20" + }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz", + "integrity": "sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-member-expression-to-functions": "^7.22.15", + "@babel/helper-optimise-call-expression": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, "node_modules/@babel/helper-simple-access": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", - "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz", + "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==", + "dev": true, "dependencies": { - "@babel/types": "^7.20.2" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-split-export-declaration": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", - "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", + "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz", - "integrity": "sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz", + "integrity": "sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==", + "dev": true, + "dependencies": { + "@babel/helper-function-name": "^7.22.5", + "@babel/template": "^7.22.15", + "@babel/types": "^7.22.19" + }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.0.tgz", - "integrity": "sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA==", + "version": "7.23.8", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.8.tgz", + "integrity": "sha512-KDqYz4PiOWvDFrdHLPhKtCThtIcKVy6avWD2oG4GEvyQ+XDZwHD4YQd+H2vNMnq2rkdxsDkU82T+Vk8U/WXHRQ==", "dependencies": { - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.0", - "@babel/types": "^7.21.0" + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.7", + "@babel/types": "^7.23.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", "dependencies": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", "js-tokens": "^4.0.0" }, "engines": { @@ -344,9 +536,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.3.tgz", - "integrity": "sha512-lobG0d7aOfQRXh8AyklEAgZGvA4FShxo6xQbUrrT/cNBPUdIDojlokwJsQyCC/eKia7ifqM0yP+2DRZ4WKw2RQ==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.6.tgz", + "integrity": "sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==", "bin": { "parser": "bin/babel-parser.js" }, @@ -354,6 +546,54 @@ "node": ">=6.0.0" } }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.23.3.tgz", + "integrity": "sha512-iRkKcCqb7iGnq9+3G6rZ+Ciz5VywC4XNRHe57lKM+jOeYAoR0lVqdeeDRfh0tQcTfw/+vBhHn926FmQhLtlFLQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.23.3.tgz", + "integrity": "sha512-WwlxbfMNdVEpQjZmK5mhm7oSwD3dS6eU+Iwsi4Knl9wAletWem7kaRsGOG+8UEbRyqxY4SS5zvtfXwX+jMxUwQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-transform-optional-chaining": "^7.23.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.23.7.tgz", + "integrity": "sha512-LlRT7HgaifEpQA1ZgLVOIJZZFVPWN5iReq/7/JixwBtwcoeVGDBD53ZV28rrsLYOZs1Y/EHhA8N/Z6aazHR8cw==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, "node_modules/@babel/plugin-proposal-export-namespace-from": { "version": "7.18.9", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz", @@ -369,6 +609,57 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "dev": true, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-syntax-dynamic-import": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", @@ -391,14 +682,13 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.21.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.21.2.tgz", - "integrity": "sha512-Cln+Yy04Gxua7iPdj6nOV96smLGjpElir5YwzF0LBPKoPlLDNJePNlrGGaybAJkd0zKRnOVXOgizSqPYMNYkzA==", + "node_modules/@babel/plugin-syntax-flow": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.23.3.tgz", + "integrity": "sha512-YZiAIpkJAwQXBJLIQbRFayR5c+gJ35Vcz3bg954k7cd73zqjvhacJuL9RbrzPz8qPmZdgqP6EUKwy0PCNhaaPA==", + "dev": true, "dependencies": { - "@babel/helper-module-transforms": "^7.21.2", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-simple-access": "^7.20.2" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -407,3745 +697,4601 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/runtime": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz", - "integrity": "sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==", + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.23.3.tgz", + "integrity": "sha512-lPgDSU+SJLK3xmFDTV2ZRQAiM7UuUjGidwBywFavObCiZc1BeAAcMtHJKUya92hPHO+at63JJPLygilZard8jw==", + "dev": true, "dependencies": { - "regenerator-runtime": "^0.13.11" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/template": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", - "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.23.3.tgz", + "integrity": "sha512-pawnE0P9g10xgoP7yKr6CK63K2FMsTE+FZidZO/1PwRdzmAPVs+HS1mAURUsgaoxammTJvULUdIkEK0gOcU2tA==", + "dev": true, "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/traverse": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.3.tgz", - "integrity": "sha512-XLyopNeaTancVitYZe2MlUEvgKb6YVVPXzofHgqHijCImG33b/uTurMS488ht/Hbsb2XK3U2BnSTxKVNGV3nGQ==", - "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.21.3", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.21.0", - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.21.3", - "@babel/types": "^7.21.3", - "debug": "^4.1.0", - "globals": "^11.1.0" + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" }, - "engines": { - "node": ">=6.9.0" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/types": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.3.tgz", - "integrity": "sha512-sBGdETxC+/M4o/zKC0sl6sjWv62WFR/uzxrJ6uYyMLZOUlPnwzw0tKgVHOXxaAd5l2g8pEDM5RZ495GPQI77kg==", + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, "dependencies": { - "@babel/helper-string-parser": "^7.19.4", - "@babel/helper-validator-identifier": "^7.19.1", - "to-fast-properties": "^2.0.0" + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz", + "integrity": "sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@colors/colors": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", - "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", "dev": true, - "optional": true, - "engines": { - "node": ">=0.1.90" + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@ctrl/tinycolor": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.0.tgz", - "integrity": "sha512-/Z3l6pXthq0JvMYdUFyX9j0MaCltlIn6mfh9jLyQwg5aPKxkyNa0PTHtU1AlFXLNk55ZuAeJRcpvq+tmLfKmaQ==", - "engines": { - "node": ">=10" + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@cubejs-client/core": { - "version": "0.31.63", - "resolved": "https://registry.npmjs.org/@cubejs-client/core/-/core-0.31.63.tgz", - "integrity": "sha512-NFlceV9G2HbFxGqTIjAqS43szRwEJDVzcfuWm/xwlAT6fU4OvZKdDXieKhaxLl38fh64m4VZefej0Mh5jwCmzQ==", + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, "dependencies": { - "@babel/runtime": "^7.1.2", - "core-js": "^3.6.5", - "cross-fetch": "^3.0.2", - "dayjs": "^1.10.4", - "ramda": "^0.27.2", - "url-search-params-polyfill": "^7.0.0", - "uuid": "^8.3.2" + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@cubejs-client/core/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "bin": { - "uuid": "dist/bin/uuid" + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@cubejs-client/vue3": { - "version": "0.31.63", - "resolved": "https://registry.npmjs.org/@cubejs-client/vue3/-/vue3-0.31.63.tgz", - "integrity": "sha512-3s2AHzavz6wudNVW7fhBtRsj0LpF6AoBRCzWm0eefMYHqxYK2ShbVEhz+c2oCM8Fri9vt7ZZt4X+70V5iPJTWw==", + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, "dependencies": { - "@cubejs-client/core": "^0.31.63", - "@vue/compiler-sfc": "^3.0.11", - "core-js": "^3.6.5", - "flush-promises": "^1.0.2", - "ramda": "^0.27.0", - "vue-loader": "^16.2.0" + "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { - "vue": "^3.0.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@cypress/request": { - "version": "2.88.11", - "resolved": "https://registry.npmjs.org/@cypress/request/-/request-2.88.11.tgz", - "integrity": "sha512-M83/wfQ1EkspjkE2lNWNV5ui2Cv7UCv1swW1DqljahbzLVWltcsexQh8jYtuS/vzFXP+HySntGM83ZXA9fn17w==", + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", "dev": true, "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "http-signature": "~1.3.6", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "performance-now": "^2.1.0", - "qs": "~6.10.3", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^8.3.2" + "@babel/helper-plugin-utils": "^7.8.0" }, - "engines": { - "node": ">= 6" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@cypress/request/node_modules/qs": { - "version": "6.10.4", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.4.tgz", - "integrity": "sha512-OQiU+C+Ds5qiH91qh/mg0w+8nwQuLjM4F4M/PbmhDOoYehPh+Fb0bDjtR1sOvy7YKxvj28Y/M0PhP5uVX0kB+g==", + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", "dev": true, "dependencies": { - "side-channel": "^1.0.4" + "@babel/helper-plugin-utils": "^7.14.5" }, "engines": { - "node": ">=0.6" + "node": ">=6.9.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@cypress/request/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", "dev": true, - "bin": { - "uuid": "dist/bin/uuid" + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@cypress/xvfb": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@cypress/xvfb/-/xvfb-1.2.4.tgz", - "integrity": "sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==", + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz", + "integrity": "sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ==", "dev": true, "dependencies": { - "debug": "^3.1.0", - "lodash.once": "^4.1.1" + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@cypress/xvfb/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", "dev": true, "dependencies": { - "ms": "^2.1.1" + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@dash14/svg-pan-zoom": { - "version": "3.6.9", - "resolved": "https://registry.npmjs.org/@dash14/svg-pan-zoom/-/svg-pan-zoom-3.6.9.tgz", - "integrity": "sha512-6u+KTQec+9+3bRdk2mReix8AGsp2mB40cw0iYfQQzo22QBkeCNpXl2amnfwQzK7xB9oH/62Wvf2z7l6l2w+csA==" - }, - "node_modules/@element-plus/icons-vue": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@element-plus/icons-vue/-/icons-vue-2.1.0.tgz", - "integrity": "sha512-PSBn3elNoanENc1vnCfh+3WA9fimRC7n+fWkf3rE5jvv+aBohNHABC/KAR5KWPecxWxDTVT1ERpRbOMRcOV/vA==", + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.23.3.tgz", + "integrity": "sha512-NzQcQrzaQPkaEwoTm4Mhyl8jI1huEL/WWIEvudjTCMJ9aBZNpsJbMASx7EQECtQQPS/DcnFpo0FIh3LvEO9cxQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, "peerDependencies": { - "vue": "^3.2.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/android-arm": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.17.tgz", - "integrity": "sha512-wHsmJG/dnL3OkpAcwbgoBTTMHVi4Uyou3F5mf58ZtmUyIKfcdA7TROav/6tCzET4A3QW2Q2FC+eFneMU+iyOxg==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "android" - ], + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.7.tgz", + "integrity": "sha512-PdxEpL71bJp1byMG0va5gwQcXHxuEYC/BgI/e88mGTtohbZN28O5Yit0Plkkm/dBzCF/BxmbNcses1RH1T+urA==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-remap-async-to-generator": "^7.22.20", + "@babel/plugin-syntax-async-generators": "^7.8.4" + }, "engines": { - "node": ">=12" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/android-arm64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.17.tgz", - "integrity": "sha512-9np+YYdNDed5+Jgr1TdWBsozZ85U1Oa3xW0c7TWqH0y2aGghXtZsuT8nYRbzOMcl0bXZXjOGbksoTtVOlWrRZg==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "android" - ], + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.23.3.tgz", + "integrity": "sha512-A7LFsKi4U4fomjqXJlZg/u0ft/n8/7n7lpffUP/ZULx/DtV9SGlNKZolHH6PE8Xl1ngCc0M11OaeZptXVkfKSw==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-remap-async-to-generator": "^7.22.20" + }, "engines": { - "node": ">=12" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/android-x64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.17.tgz", - "integrity": "sha512-O+FeWB/+xya0aLg23hHEM2E3hbfwZzjqumKMSIqcHbNvDa+dza2D0yLuymRBQQnC34CWrsJUXyH2MG5VnLd6uw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "android" - ], + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.23.3.tgz", + "integrity": "sha512-vI+0sIaPIO6CNuM9Kk5VmXcMVRiOpDh7w2zZt9GXzmE/9KD70CUEVhvPR/etAeNK/FAEkhxQtXOzVF3EuRL41A==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, "engines": { - "node": ">=12" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.17.tgz", - "integrity": "sha512-M9uJ9VSB1oli2BE/dJs3zVr9kcCBBsE883prage1NWz6pBS++1oNn/7soPNS3+1DGj0FrkSvnED4Bmlu1VAE9g==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "darwin" - ], + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.4.tgz", + "integrity": "sha512-0QqbP6B6HOh7/8iNR4CQU2Th/bbRtBp4KS9vcaZd1fZ0wSh5Fyssg0UCIHwxh+ka+pNDREbVLQnHCMHKZfPwfw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, "engines": { - "node": ">=12" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.17.tgz", - "integrity": "sha512-XDre+J5YeIJDMfp3n0279DFNrGCXlxOuGsWIkRb1NThMZ0BsrWXoTg23Jer7fEXQ9Ye5QjrvXpxnhzl3bHtk0g==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" - ], + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.23.3.tgz", + "integrity": "sha512-uM+AN8yCIjDPccsKGlw271xjJtGii+xQIF/uMPS8H15L12jZTsLfF4o5vNO7d/oUguOyfdikHGc/yi9ge4SGIg==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + }, "engines": { - "node": ">=12" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.17.tgz", - "integrity": "sha512-cjTzGa3QlNfERa0+ptykyxs5A6FEUQQF0MuilYXYBGdBxD3vxJcKnzDlhDCa1VAJCmAxed6mYhA2KaJIbtiNuQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "freebsd" - ], + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.23.4.tgz", + "integrity": "sha512-nsWu/1M+ggti1SOALj3hfx5FXzAY06fwPJsUZD4/A5e1bWi46VUIWtD+kOX6/IdhXGsXBWllLFDSnqSCdUNydQ==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + }, "engines": { - "node": ">=12" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" } }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.17.tgz", - "integrity": "sha512-sOxEvR8d7V7Kw8QqzxWc7bFfnWnGdaFBut1dRUYtu+EIRXefBc/eIsiUiShnW0hM3FmQ5Zf27suDuHsKgZ5QrA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "freebsd" - ], + "node_modules/@babel/plugin-transform-classes": { + "version": "7.23.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.23.8.tgz", + "integrity": "sha512-yAYslGsY1bX6Knmg46RjiCiNSwJKv2IUC8qOdYKqMMr0491SXFhcHqOdRDeCRohOOIzwN/90C6mQ9qAKgrP7dg==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.20", + "@babel/helper-split-export-declaration": "^7.22.6", + "globals": "^11.1.0" + }, "engines": { - "node": ">=12" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/linux-arm": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.17.tgz", - "integrity": "sha512-2d3Lw6wkwgSLC2fIvXKoMNGVaeY8qdN0IC3rfuVxJp89CRfA3e3VqWifGDfuakPmp90+ZirmTfye1n4ncjv2lg==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "linux" - ], + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.23.3.tgz", + "integrity": "sha512-dTj83UVTLw/+nbiHqQSFdwO9CbTtwq1DsDqm3CUEtDrZNET5rT5E6bIdTlOftDTDLMYxvxHNEYO4B9SLl8SLZw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/template": "^7.22.15" + }, "engines": { - "node": ">=12" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.17.tgz", - "integrity": "sha512-c9w3tE7qA3CYWjT+M3BMbwMt+0JYOp3vCMKgVBrCl1nwjAlOMYzEo+gG7QaZ9AtqZFj5MbUc885wuBBmu6aADQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.3.tgz", + "integrity": "sha512-n225npDqjDIr967cMScVKHXJs7rout1q+tt50inyBCPkyZ8KxeI6d+GIbSBTT/w/9WdlWDOej3V9HE5Lgk57gw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, "engines": { - "node": ">=12" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.17.tgz", - "integrity": "sha512-1DS9F966pn5pPnqXYz16dQqWIB0dmDfAQZd6jSSpiT9eX1NzKh07J6VKR3AoXXXEk6CqZMojiVDSZi1SlmKVdg==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "linux" - ], + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.23.3.tgz", + "integrity": "sha512-vgnFYDHAKzFaTVp+mneDsIEbnJ2Np/9ng9iviHw3P/KVcgONxpNULEW/51Z/BaFojG2GI2GwwXck5uV1+1NOYQ==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + }, "engines": { - "node": ">=12" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.17.tgz", - "integrity": "sha512-EvLsxCk6ZF0fpCB6w6eOI2Fc8KW5N6sHlIovNe8uOFObL2O+Mr0bflPHyHwLT6rwMg9r77WOAWb2FqCQrVnwFg==", - "cpu": [ - "loong64" - ], - "optional": true, - "os": [ - "linux" - ], + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.23.3.tgz", + "integrity": "sha512-RrqQ+BQmU3Oyav3J+7/myfvRCq7Tbz+kKLLshUmMwNlDHExbGL7ARhajvoBJEvc+fCguPPu887N+3RRXBVKZUA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, "engines": { - "node": ">=12" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.17.tgz", - "integrity": "sha512-e0bIdHA5p6l+lwqTE36NAW5hHtw2tNRmHlGBygZC14QObsA3bD4C6sXLJjvnDIjSKhW1/0S3eDy+QmX/uZWEYQ==", - "cpu": [ - "mips64el" - ], - "optional": true, - "os": [ - "linux" - ], + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.23.4.tgz", + "integrity": "sha512-V6jIbLhdJK86MaLh4Jpghi8ho5fGzt3imHOBu/x0jlBaPYqDoWz4RDXjmMOfnh+JWNaQleEAByZLV0QzBT4YQQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, "engines": { - "node": ">=12" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.17.tgz", - "integrity": "sha512-BAAilJ0M5O2uMxHYGjFKn4nJKF6fNCdP1E0o5t5fvMYYzeIqy2JdAP88Az5LHt9qBoUa4tDaRpfWt21ep5/WqQ==", - "cpu": [ - "ppc64" - ], - "optional": true, - "os": [ - "linux" - ], + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.23.3.tgz", + "integrity": "sha512-5fhCsl1odX96u7ILKHBj4/Y8vipoqwsJMh4csSA8qFfxrZDEA4Ssku2DyNvMJSmZNOEBT750LfFPbtrnTP90BQ==", + "dev": true, + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + }, "engines": { - "node": ">=12" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.17.tgz", - "integrity": "sha512-Wh/HW2MPnC3b8BqRSIme/9Zhab36PPH+3zam5pqGRH4pE+4xTrVLx2+XdGp6fVS3L2x+DrsIcsbMleex8fbE6g==", - "cpu": [ - "riscv64" - ], - "optional": true, - "os": [ - "linux" - ], + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.23.4.tgz", + "integrity": "sha512-GzuSBcKkx62dGzZI1WVgTWvkkz84FZO5TC5T8dl/Tht/rAla6Dg/Mz9Yhypg+ezVACf/rgDuQt3kbWEv7LdUDQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + }, "engines": { - "node": ">=12" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.17.tgz", - "integrity": "sha512-j/34jAl3ul3PNcK3pfI0NSlBANduT2UO5kZ7FCaK33XFv3chDhICLY8wJJWIhiQ+YNdQ9dxqQctRg2bvrMlYgg==", - "cpu": [ - "s390x" - ], - "optional": true, - "os": [ - "linux" - ], + "node_modules/@babel/plugin-transform-flow-strip-types": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.23.3.tgz", + "integrity": "sha512-26/pQTf9nQSNVJCrLB1IkHUKyPxR+lMrH2QDPG89+Znu9rAMbtrybdbWeE9bb7gzjmE5iXHEY+e0HUwM6Co93Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-flow": "^7.23.3" + }, "engines": { - "node": ">=12" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/linux-x64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.17.tgz", - "integrity": "sha512-QM50vJ/y+8I60qEmFxMoxIx4de03pGo2HwxdBeFd4nMh364X6TIBZ6VQ5UQmPbQWUVWHWws5MmJXlHAXvJEmpQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.23.6.tgz", + "integrity": "sha512-aYH4ytZ0qSuBbpfhuofbg/e96oQ7U2w1Aw/UQmKT+1l39uEhUPoFS3fHevDc1G0OvewyDudfMKY1OulczHzWIw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + }, "engines": { - "node": ">=12" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.17.tgz", - "integrity": "sha512-/jGlhWR7Sj9JPZHzXyyMZ1RFMkNPjC6QIAan0sDOtIo2TYk3tZn5UDrkE0XgsTQCxWTTOcMPf9p6Rh2hXtl5TQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "netbsd" - ], + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.23.3.tgz", + "integrity": "sha512-I1QXp1LxIvt8yLaib49dRW5Okt7Q4oaxao6tFVKS/anCdEOMtYwWVKoiOA1p34GOWIZjUK0E+zCp7+l1pfQyiw==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-plugin-utils": "^7.22.5" + }, "engines": { - "node": ">=12" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.17.tgz", - "integrity": "sha512-rSEeYaGgyGGf4qZM2NonMhMOP/5EHp4u9ehFiBrg7stH6BYEEjlkVREuDEcQ0LfIl53OXLxNbfuIj7mr5m29TA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "openbsd" - ], + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.23.4.tgz", + "integrity": "sha512-81nTOqM1dMwZ/aRXQ59zVubN9wHGqk6UtqRK+/q+ciXmRy8fSolhGVvG09HHRGo4l6fr/c4ZhXUQH0uFW7PZbg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-json-strings": "^7.8.3" + }, "engines": { - "node": ">=12" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.17.tgz", - "integrity": "sha512-Y7ZBbkLqlSgn4+zot4KUNYst0bFoO68tRgI6mY2FIM+b7ZbyNVtNbDP5y8qlu4/knZZ73fgJDlXID+ohY5zt5g==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "sunos" - ], + "node_modules/@babel/plugin-transform-literals": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.23.3.tgz", + "integrity": "sha512-wZ0PIXRxnwZvl9AYpqNUxpZ5BiTGrYt7kueGQ+N5FiQ7RCOD4cm8iShd6S6ggfVIWaJf2EMk8eRzAh52RfP4rQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, "engines": { - "node": ">=12" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.17.tgz", - "integrity": "sha512-bwPmTJsEQcbZk26oYpc4c/8PvTY3J5/QK8jM19DVlEsAB41M39aWovWoHtNm78sd6ip6prilxeHosPADXtEJFw==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "win32" - ], + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.23.4.tgz", + "integrity": "sha512-Mc/ALf1rmZTP4JKKEhUwiORU+vcfarFVLfcFiolKUo6sewoxSEgl36ak5t+4WamRsNr6nzjZXQjM35WsU+9vbg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, "engines": { - "node": ">=12" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.17.tgz", - "integrity": "sha512-H/XaPtPKli2MhW+3CQueo6Ni3Avggi6hP/YvgkEe1aSaxw+AeO8MFjq8DlgfTd9Iz4Yih3QCZI6YLMoyccnPRg==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "win32" - ], + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.23.3.tgz", + "integrity": "sha512-sC3LdDBDi5x96LA+Ytekz2ZPk8i/Ck+DEuDbRAll5rknJ5XRTSaPKEYwomLcs1AA8wg9b3KjIQRsnApj+q51Ag==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, "engines": { - "node": ">=12" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/win32-x64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.17.tgz", - "integrity": "sha512-fGEb8f2BSA3CW7riJVurug65ACLuQAzKq0SSqkY2b2yHHH0MzDfbLyKIGzHwOI/gkHcxM/leuSW6D5w/LMNitA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "win32" - ], + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.23.3.tgz", + "integrity": "sha512-vJYQGxeKM4t8hYCKVBlZX/gtIY2I7mRGFNcm85sgXGMTBcoV3QdVtdpbcWEbzbfUIUZKwvgFT82mRvaQIebZzw==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.22.5" + }, "engines": { - "node": ">=12" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.3.tgz", + "integrity": "sha512-aVS0F65LKsdNOtcz6FRCpE4OgsP2OFnW46qNxNIX9h3wuzaNcSQsJysuMwqSibC98HPrf2vCgtxKNwS0DAlgcA==", "dependencies": { - "eslint-visitor-keys": "^3.3.0" + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-simple-access": "^7.22.5" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=6.9.0" }, "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@eslint-community/regexpp": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.4.1.tgz", - "integrity": "sha512-BISJ6ZE4xQsuL/FmsyRaiffpq977bMlsKfGHTQrOGFErfByxIe6iZTxPf/00Zon9b9a7iUykfQwejN3s2ZW/Bw==", + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.3.tgz", + "integrity": "sha512-ZxyKGTkF9xT9YJuKQRo19ewf3pXpopuYQd8cDXqNzc3mUNbOME0RKMoZxviQk74hwzfQsEe66dE92MaZbdHKNQ==", + "dev": true, + "dependencies": { + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20" + }, "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@eslint/eslintrc": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.1.tgz", - "integrity": "sha512-eFRmABvW2E5Ho6f5fHLqgena46rOj7r7OKHYfLElqcBfGFHHpjBhivyi5+jOEQuSpdc/1phIZJlbC2te+tZNIw==", + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.23.3.tgz", + "integrity": "sha512-zHsy9iXX2nIsCBFPud3jKn1IRPWg3Ing1qOZgeKV39m1ZgIdpJqvlWVeiHBZC6ITRG0MfskhYe9cLgntfSFPIg==", + "dev": true, "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.5.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=6.9.0" }, - "funding": { - "url": "https://opencollective.com/eslint" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz", + "integrity": "sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==", + "dev": true, "dependencies": { - "type-fest": "^0.20.2" + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { - "node": ">=8" + "node": ">=6.9.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@eslint/eslintrc/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.23.3.tgz", + "integrity": "sha512-YJ3xKqtJMAT5/TIZnpAR3I+K+WaDowYbN3xyxI8zxx/Gsypwf9B9h0VB+1Nh6ACAAPRS5NSRje0uVv5i79HYGQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, "engines": { - "node": ">=10" + "node": ">=6.9.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@eslint/js": { - "version": "8.36.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.36.0.tgz", - "integrity": "sha512-lxJ9R5ygVm8ZWgYdUweoq5ownDlJ4upvoWmO4eLxBYHdMo+vZ/Rx0EN6MbKWDJOSUGrqJy2Gt+Dyv/VKml0fjg==", + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.23.4.tgz", + "integrity": "sha512-jHE9EVVqHKAQx+VePv5LLGHjmHSJR76vawFPTdlxR/LVJPfOEGxREQwQfjuZEOPTwG92X3LINSh3M40Rv4zpVA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@floating-ui/core": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.2.5.tgz", - "integrity": "sha512-qrcbyfnRVziRlB6IYwjCopYhO7Vud750JlJyuljruIXcPxr22y8zdckcJGsuOdnQ639uVD1tTXddrcH3t3QYIQ==" - }, - "node_modules/@floating-ui/dom": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.2.5.tgz", - "integrity": "sha512-+sAUfpQ3Frz+VCbPCqj+cZzvEESy3fjSeT/pDWkYCWOBXYNNKZfuVsHuv8/JO2zze8+Eb/Q7a6hZVgzS81fLbQ==", + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.23.4.tgz", + "integrity": "sha512-mps6auzgwjRrwKEZA05cOwuDc9FAzoyFS4ZsG/8F43bTLf/TgkJg7QXOrPO1JO599iA3qgK9MXdMGOEC8O1h6Q==", + "dev": true, "dependencies": { - "@floating-ui/core": "^1.2.4" + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@formbricks/js": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@formbricks/js/-/js-1.2.0.tgz", - "integrity": "sha512-bhQutlEHWnMHm54h6tc2VRM8lj/Rio0tT1L+zNjFv0Hcx4TamZ/967MyhGpY0LnJyqdr8Ck/+DtEWFSAOO5HEw==" - }, - "node_modules/@hapi/hoek": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", - "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==", - "dev": true - }, - "node_modules/@hapi/topo": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", - "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.23.4.tgz", + "integrity": "sha512-9x9K1YyeQVw0iOXJlIzwm8ltobIIv7j2iLyP2jIhEbqPRQ7ScNgwQufU2I0Gq11VjyG4gI4yMXt2VFags+1N3g==", "dev": true, "dependencies": { - "@hapi/hoek": "^9.0.0" + "@babel/compat-data": "^7.23.3", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.23.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.8", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", - "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.23.3.tgz", + "integrity": "sha512-BwQ8q0x2JG+3lxCVFohg+KbQM7plfpBwThdW9A6TMtWwLsbDA01Ek2Zb/AgDN39BiZsExm4qrXxjk+P1/fzGrA==", + "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.5" + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.20" }, "engines": { - "node": ">=10.10.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.23.4.tgz", + "integrity": "sha512-XIq8t0rJPHf6Wvmbn9nFxU6ao4c7WhghTR5WyV8SrJfUFzyxhCm4nhC+iAp3HFhbAKLfYpgzhJ6t4XCtVwqO5A==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, "engines": { - "node": ">=12.22" + "node": ">=6.9.0" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==" - }, - "node_modules/@interactjs/actions": { - "version": "1.10.17", - "resolved": "https://registry.npmjs.org/@interactjs/actions/-/actions-1.10.17.tgz", - "integrity": "sha512-wyB1ZqpaZy5gmz6VDqK9KWh98xKnFgL7VyLvxHODFi9V0IYX4HJAAOBlhtfze0D1R1f1cY+gqPDK+dLaHMlE+w==", - "optionalDependencies": { - "@interactjs/interact": "1.10.17" + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.4.tgz", + "integrity": "sha512-ZU8y5zWOfjM5vZ+asjgAPwDaBjJzgufjES89Rs4Lpq63O300R/kOz30WCLo6BxxX6QVEilwSlpClnG5cZaikTA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { - "@interactjs/core": "1.10.17", - "@interactjs/utils": "1.10.17" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@interactjs/auto-scroll": { - "version": "1.10.17", - "resolved": "https://registry.npmjs.org/@interactjs/auto-scroll/-/auto-scroll-1.10.17.tgz", - "integrity": "sha512-IQcW7N3xOaoL8RnAGOGMk0Y2gue7L4S3BT6Id4VBBu8so163DtLiZVW6jXu9rKVntzbluaAeqNZlfAVyu3kIWg==", - "optionalDependencies": { - "@interactjs/interact": "1.10.17" + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.23.3.tgz", + "integrity": "sha512-09lMt6UsUb3/34BbECKVbVwrT9bO6lILWln237z7sLaWnMsTi7Yc9fhX5DLpkJzAGfaReXI22wP41SZmnAA3Vw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { - "@interactjs/utils": "1.10.17" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@interactjs/auto-start": { - "version": "1.10.17", - "resolved": "https://registry.npmjs.org/@interactjs/auto-start/-/auto-start-1.10.17.tgz", - "integrity": "sha512-qYVxhAbYnwxjD/NLEegUoAST7WASJ4VmWNjsyWRx/js5Op+I4E2zteARIeZGgrutcGIXMCcQzhCMgE3PjOpbpw==", - "optionalDependencies": { - "@interactjs/interact": "1.10.17" + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.23.3.tgz", + "integrity": "sha512-UzqRcRtWsDMTLrRWFvUBDwmw06tCQH9Rl1uAjfh6ijMSmGYQ+fpdB+cnqRC8EMh5tuuxSv0/TejGL+7vyj+50g==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { - "@interactjs/core": "1.10.17", - "@interactjs/utils": "1.10.17" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@interactjs/core": { - "version": "1.10.17", - "resolved": "https://registry.npmjs.org/@interactjs/core/-/core-1.10.17.tgz", - "integrity": "sha512-rL9w+83HDRuXub8Ezqs+97CYLl/ne7bLT/sAeduUWaxYhsW9iOqBoob9JnkkCZOaOsYizWI1EWy0+fNc5ibtLQ==", + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.23.4.tgz", + "integrity": "sha512-9G3K1YqTq3F4Vt88Djx1UZ79PDyj+yKRnUy7cZGSMe+a7jkwD259uKKuUzQlPkGam7R+8RJwh5z4xO27fA1o2A==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, "peerDependencies": { - "@interactjs/utils": "1.10.17" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@interactjs/dev-tools": { - "version": "1.10.17", - "resolved": "https://registry.npmjs.org/@interactjs/dev-tools/-/dev-tools-1.10.17.tgz", - "integrity": "sha512-Oi9nEw3FfSwkNmW+V0WwdHqvzEkVHc24mH1v5EjRn60sqgrGLK9nTQ+NSuqcnUY8GxC3TkyuxnsOodxiadIRmA==", - "optionalDependencies": { - "@interactjs/interact": "1.10.17" + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.23.3.tgz", + "integrity": "sha512-jR3Jn3y7cZp4oEWPFAlRsSWjxKe4PZILGBSd4nis1TsC5qeSpb+nrtihJuDhNI7QHiVbUaiXa0X2RZY3/TI6Nw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { - "@interactjs/modifiers": "1.10.17", - "@interactjs/utils": "1.10.17" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@interactjs/inertia": { - "version": "1.10.17", - "resolved": "https://registry.npmjs.org/@interactjs/inertia/-/inertia-1.10.17.tgz", - "integrity": "sha512-41vbYUjZIDCKt2/yhmjPrEW5+0uoL/hldFsll9pkvnLhmm12Xk0VXOlmR2zXKAmsTK3fJlKMyBYUX92qHLkyVQ==", + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.23.3.tgz", + "integrity": "sha512-KP+75h0KghBMcVpuKisx3XTu9Ncut8Q8TuvGO4IhY+9D5DFEckQefOuIsB/gQ2tG71lCke4NMrtIPS8pOj18BQ==", + "dev": true, "dependencies": { - "@interactjs/offset": "1.10.17" + "@babel/helper-plugin-utils": "^7.22.5", + "regenerator-transform": "^0.15.2" }, - "optionalDependencies": { - "@interactjs/interact": "1.10.17" + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { - "@interactjs/core": "1.10.17", - "@interactjs/modifiers": "1.10.17", - "@interactjs/utils": "1.10.17" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@interactjs/interact": { - "version": "1.10.17", - "resolved": "https://registry.npmjs.org/@interactjs/interact/-/interact-1.10.17.tgz", - "integrity": "sha512-NyKsf8EFudvdahBjPz1Gt5QnynVwa/2LUfBc2/w8QOnOBiyzUm0HLloJSaB8a50QbQkSWN243/Lgpd8GTMQvuQ==", + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.23.3.tgz", + "integrity": "sha512-QnNTazY54YqgGxwIexMZva9gqbPa15t/x9VS+0fsEFWplwVpXYZivtgl43Z1vMpc1bdPP2PP8siFeVcnFvA3Cg==", + "dev": true, "dependencies": { - "@interactjs/core": "1.10.17", - "@interactjs/types": "1.10.17", - "@interactjs/utils": "1.10.17" + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@interactjs/interactjs": { - "version": "1.10.17", - "resolved": "https://registry.npmjs.org/@interactjs/interactjs/-/interactjs-1.10.17.tgz", - "integrity": "sha512-hHmiukARbZhiM12zNKx0yQlFVl4C+NMeYNAYh6Mf9U3ZziQ47C+JEW8Gr7Zr/MxfNZyPu5nLKCpVQjh/JvBO9g==", + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.23.3.tgz", + "integrity": "sha512-ED2fgqZLmexWiN+YNFX26fx4gh5qHDhn1O2gvEhreLW2iI63Sqm4llRLCXALKrCnbN4Jy0VcMQZl/SAzqug/jg==", + "dev": true, "dependencies": { - "@interactjs/actions": "1.10.17", - "@interactjs/auto-scroll": "1.10.17", - "@interactjs/auto-start": "1.10.17", - "@interactjs/core": "1.10.17", - "@interactjs/dev-tools": "1.10.17", - "@interactjs/inertia": "1.10.17", - "@interactjs/interact": "1.10.17", - "@interactjs/modifiers": "1.10.17", - "@interactjs/offset": "1.10.17", - "@interactjs/pointer-events": "1.10.17", - "@interactjs/reflow": "1.10.17", - "@interactjs/utils": "1.10.17" + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@interactjs/modifiers": { - "version": "1.10.17", - "resolved": "https://registry.npmjs.org/@interactjs/modifiers/-/modifiers-1.10.17.tgz", - "integrity": "sha512-Dxw8kv9VBIxnhNvQncR6CKAGMzKXczLvuAUIdSPFYtyerX/XiDulJUqhR+jVKNp/WjF1DvdBxWo0kGGLbM84LQ==", + "node_modules/@babel/plugin-transform-spread": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.23.3.tgz", + "integrity": "sha512-VvfVYlrlBVu+77xVTOAoxQ6mZbnIq5FM0aGBSFEcIh03qHf+zNqA4DC/3XMUozTg7bZV3e3mZQ0i13VB6v5yUg==", + "dev": true, "dependencies": { - "@interactjs/snappers": "1.10.17" + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" }, - "optionalDependencies": { - "@interactjs/interact": "1.10.17" + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { - "@interactjs/core": "1.10.17", - "@interactjs/utils": "1.10.17" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@interactjs/offset": { - "version": "1.10.17", - "resolved": "https://registry.npmjs.org/@interactjs/offset/-/offset-1.10.17.tgz", - "integrity": "sha512-wWBnIQWgLrmJNTBbd/FdxHxAJjiXl/5ND8Jbw2DuP9gIGDxhFSdEt62Fgqimn9ICb8v8ycvSLObEmcvJF/8hQQ==", - "optionalDependencies": { - "@interactjs/interact": "1.10.17" + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.23.3.tgz", + "integrity": "sha512-HZOyN9g+rtvnOU3Yh7kSxXrKbzgrm5X4GncPY1QOquu7epga5MxKHVpYu2hvQnry/H+JjckSYRb93iNfsioAGg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { - "@interactjs/core": "1.10.17", - "@interactjs/utils": "1.10.17" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@interactjs/pointer-events": { - "version": "1.10.17", - "resolved": "https://registry.npmjs.org/@interactjs/pointer-events/-/pointer-events-1.10.17.tgz", - "integrity": "sha512-VsfluouEKb8QRGyH6jQATCW+QdAd/3dkENS7rj2m+EcVUhz2Ob5mpMRopjALi4pwltMowqTfuJ4LtwMSX2G29A==", - "optionalDependencies": { - "@interactjs/interact": "1.10.17" + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.23.3.tgz", + "integrity": "sha512-Flok06AYNp7GV2oJPZZcP9vZdszev6vPBkHLwxwSpaIqx75wn6mUd3UFWsSsA0l8nXAKkyCmL/sR02m8RYGeHg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { - "@interactjs/core": "1.10.17", - "@interactjs/utils": "1.10.17" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@interactjs/reflow": { - "version": "1.10.17", - "resolved": "https://registry.npmjs.org/@interactjs/reflow/-/reflow-1.10.17.tgz", - "integrity": "sha512-ncpWP5k93FRQptEhjzPZsbuRRajd4rkW17lDavCrEjrDi/LHnYekWGqZTaFzfJ80n1x8xUm9ujDjxCTylNqEIA==", - "optionalDependencies": { - "@interactjs/interact": "1.10.17" + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.23.3.tgz", + "integrity": "sha512-4t15ViVnaFdrPC74be1gXBSMzXk3B4Us9lP7uLRQHTFpV5Dvt33pn+2MyyNxmN3VTTm3oTrZVMUmuw3oBnQ2oQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { - "@interactjs/core": "1.10.17", - "@interactjs/utils": "1.10.17" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@interactjs/snappers": { - "version": "1.10.17", - "resolved": "https://registry.npmjs.org/@interactjs/snappers/-/snappers-1.10.17.tgz", - "integrity": "sha512-m753DGsNOts797e3zDT6wqELoc+BlpIC1w+TyMyISRxU6n1RlS8Q6LHBGgwAgV79LHLaahv/a5haFF9H1VG0FQ==", - "optionalDependencies": { - "@interactjs/interact": "1.10.17" + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.23.6.tgz", + "integrity": "sha512-6cBG5mBvUu4VUD04OHKnYzbuHNP8huDsD3EDqqpIpsswTDoqHCjLoHb6+QgsV1WsT2nipRqCPgxD3LXnEO7XfA==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.23.6", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-typescript": "^7.23.3" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { - "@interactjs/utils": "1.10.17" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@interactjs/types": { - "version": "1.10.17", - "resolved": "https://registry.npmjs.org/@interactjs/types/-/types-1.10.17.tgz", - "integrity": "sha512-X2JpoM7xUw0p9Me0tMaI0HNfcF/Hd07ZZlzpnpEMpGerUZOLoyeThrV9P+CrBHxZrluWJrigJbcdqXliFd0YMA==" - }, - "node_modules/@interactjs/utils": { - "version": "1.10.17", - "resolved": "https://registry.npmjs.org/@interactjs/utils/-/utils-1.10.17.tgz", - "integrity": "sha512-sZAW08CkqgvqRjUIaLRjScjObcCzN9D75yekLA21EClYAZIhi4A+GEt2z/WqOCOksTaEPLYmQyhkpXcboc0LhQ==" - }, - "node_modules/@jest/schemas": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.3.tgz", - "integrity": "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==", + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.23.3.tgz", + "integrity": "sha512-OMCUx/bU6ChE3r4+ZdylEqAjaQgHAgipgW8nsCfu5pGqDcFytVd91AwRvUJSBZDz0exPGgnjoqhgRYLRjFZc9Q==", "dev": true, "dependencies": { - "@sinclair/typebox": "^0.25.16" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/types": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.5.0.tgz", - "integrity": "sha512-qbu7kN6czmVRc3xWFQcAN03RAUamgppVUdXrvl1Wr3jlNF93o9mJbGcDWrwGB6ht44u7efB1qCFgVQmca24Uog==", + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.23.3.tgz", + "integrity": "sha512-KcLIm+pDZkWZQAFJ9pdfmh89EwVfmNovFBcXko8szpBeF8z68kWIPeKlmSOkT9BXJxs2C0uk+5LxoxIv62MROA==", "dev": true, "dependencies": { - "@jest/schemas": "^29.4.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" + "@babel/helper-create-regexp-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/types/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.23.3.tgz", + "integrity": "sha512-wMHpNA4x2cIA32b/ci3AfwNgheiva2W0WUKWTK7vBHBhDKfPsc5cFGNWm69WBqpwd86u1qwZ9PWevKqm1A3yAw==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "@babel/helper-create-regexp-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { - "node": ">=8" + "node": ">=6.9.0" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/types/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.23.3.tgz", + "integrity": "sha512-W7lliA/v9bNR83Qc3q1ip9CQMZ09CcHDbHfbLRDNuAhn1Mvkr1ZNF7hPmztMQvtTGVLJ9m8IZqWsTkXOml8dbw==", "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "@babel/helper-create-regexp-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { - "node": ">=10" + "node": ">=6.9.0" }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@jest/types/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/@babel/preset-env": { + "version": "7.23.8", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.23.8.tgz", + "integrity": "sha512-lFlpmkApLkEP6woIKprO6DO60RImpatTQKtz4sUcDjVcK8M8mQ4sZsuxaTMNOZf0sqAq/ReYW1ZBHnOQwKpLWA==", "dev": true, "dependencies": { - "color-name": "~1.1.4" + "@babel/compat-data": "^7.23.5", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-option": "^7.23.5", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.23.3", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.23.3", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.23.7", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.23.3", + "@babel/plugin-syntax-import-attributes": "^7.23.3", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.23.3", + "@babel/plugin-transform-async-generator-functions": "^7.23.7", + "@babel/plugin-transform-async-to-generator": "^7.23.3", + "@babel/plugin-transform-block-scoped-functions": "^7.23.3", + "@babel/plugin-transform-block-scoping": "^7.23.4", + "@babel/plugin-transform-class-properties": "^7.23.3", + "@babel/plugin-transform-class-static-block": "^7.23.4", + "@babel/plugin-transform-classes": "^7.23.8", + "@babel/plugin-transform-computed-properties": "^7.23.3", + "@babel/plugin-transform-destructuring": "^7.23.3", + "@babel/plugin-transform-dotall-regex": "^7.23.3", + "@babel/plugin-transform-duplicate-keys": "^7.23.3", + "@babel/plugin-transform-dynamic-import": "^7.23.4", + "@babel/plugin-transform-exponentiation-operator": "^7.23.3", + "@babel/plugin-transform-export-namespace-from": "^7.23.4", + "@babel/plugin-transform-for-of": "^7.23.6", + "@babel/plugin-transform-function-name": "^7.23.3", + "@babel/plugin-transform-json-strings": "^7.23.4", + "@babel/plugin-transform-literals": "^7.23.3", + "@babel/plugin-transform-logical-assignment-operators": "^7.23.4", + "@babel/plugin-transform-member-expression-literals": "^7.23.3", + "@babel/plugin-transform-modules-amd": "^7.23.3", + "@babel/plugin-transform-modules-commonjs": "^7.23.3", + "@babel/plugin-transform-modules-systemjs": "^7.23.3", + "@babel/plugin-transform-modules-umd": "^7.23.3", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5", + "@babel/plugin-transform-new-target": "^7.23.3", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.23.4", + "@babel/plugin-transform-numeric-separator": "^7.23.4", + "@babel/plugin-transform-object-rest-spread": "^7.23.4", + "@babel/plugin-transform-object-super": "^7.23.3", + "@babel/plugin-transform-optional-catch-binding": "^7.23.4", + "@babel/plugin-transform-optional-chaining": "^7.23.4", + "@babel/plugin-transform-parameters": "^7.23.3", + "@babel/plugin-transform-private-methods": "^7.23.3", + "@babel/plugin-transform-private-property-in-object": "^7.23.4", + "@babel/plugin-transform-property-literals": "^7.23.3", + "@babel/plugin-transform-regenerator": "^7.23.3", + "@babel/plugin-transform-reserved-words": "^7.23.3", + "@babel/plugin-transform-shorthand-properties": "^7.23.3", + "@babel/plugin-transform-spread": "^7.23.3", + "@babel/plugin-transform-sticky-regex": "^7.23.3", + "@babel/plugin-transform-template-literals": "^7.23.3", + "@babel/plugin-transform-typeof-symbol": "^7.23.3", + "@babel/plugin-transform-unicode-escapes": "^7.23.3", + "@babel/plugin-transform-unicode-property-regex": "^7.23.3", + "@babel/plugin-transform-unicode-regex": "^7.23.3", + "@babel/plugin-transform-unicode-sets-regex": "^7.23.3", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.7", + "babel-plugin-polyfill-corejs3": "^0.8.7", + "babel-plugin-polyfill-regenerator": "^0.5.4", + "core-js-compat": "^3.31.0", + "semver": "^6.3.1" }, "engines": { - "node": ">=7.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/types/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@jest/types/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==", + "node_modules/@babel/preset-flow": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.23.3.tgz", + "integrity": "sha512-7yn6hl8RIv+KNk6iIrGZ+D06VhVY35wLVf23Cz/mMu1zOr7u4MMP4j0nZ9tLf8+4ZFpnib8cFYgB/oYg9hfswA==", "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-option": "^7.22.15", + "@babel/plugin-transform-flow-strip-types": "^7.23.3" + }, "engines": { - "node": ">=8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/types/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" }, - "engines": { - "node": ">=8" + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" } }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "node_modules/@babel/preset-typescript": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.23.3.tgz", + "integrity": "sha512-17oIGVlqz6CchO9RFYn5U6ZpWRZIngayYCtrPRSgANSwC2V1Jb+iP74nVxzzXJte8b8BYxrL1yY96xfhTBrNNQ==", + "dev": true, "dependencies": { - "@jridgewell/set-array": "^1.0.0", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-option": "^7.22.15", + "@babel/plugin-syntax-jsx": "^7.23.3", + "@babel/plugin-transform-modules-commonjs": "^7.23.3", + "@babel/plugin-transform-typescript": "^7.23.3" }, "engines": { - "node": ">=6.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "node_modules/@babel/register": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.23.7.tgz", + "integrity": "sha512-EjJeB6+kvpk+Y5DAkEAmbOBEFkh9OASx0huoEkqYTFxAZHzOAX2Oh5uwAUuL2rUddqfM0SA+KPXV2TbzoZ2kvQ==", + "dev": true, + "dependencies": { + "clone-deep": "^4.0.1", + "find-cache-dir": "^2.0.0", + "make-dir": "^2.1.0", + "pirates": "^4.0.6", + "source-map-support": "^0.5.16" + }, "engines": { - "node": ">=6.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "node_modules/@babel/register/node_modules/find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, "engines": { - "node": ">=6.0.0" + "node": ">=6" } }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", - "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "node_modules/@babel/register/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" } }, - "node_modules/@jridgewell/source-map/node_modules/@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "node_modules/@babel/register/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" }, "engines": { - "node": ">=6.0.0" + "node": ">=6" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", - "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", + "node_modules/@babel/register/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" } }, - "node_modules/@koa/router": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/@koa/router/-/router-9.4.0.tgz", - "integrity": "sha512-dOOXgzqaDoHu5qqMEPLKEgLz5CeIA7q8+1W62mCvFVCOqeC71UoTGJ4u1xUSOpIl2J1x2pqrNULkFteUeZW3/A==", + "node_modules/@babel/register/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "dependencies": { - "debug": "^4.1.1", - "http-errors": "^1.7.3", - "koa-compose": "^4.1.0", - "methods": "^1.1.2", - "path-to-regexp": "^6.1.0" + "p-try": "^2.0.0" }, "engines": { - "node": ">= 8.0.0" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@linaria/core": { - "version": "4.2.9", - "resolved": "https://registry.npmjs.org/@linaria/core/-/core-4.2.9.tgz", - "integrity": "sha512-ELcu37VNVOT/PU0L6WDIN+aLzNFyJrqoBYT0CucGOCAmODbojUMCv8oJYRbWzA3N34w1t199dN4UFdfRWFG2rg==", + "node_modules/@babel/register/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, "dependencies": { - "@linaria/logger": "^4.0.0", - "@linaria/tags": "^4.3.4", - "@linaria/utils": "^4.3.3" + "p-limit": "^2.0.0" }, "engines": { - "node": "^12.16.0 || >=13.7.0" + "node": ">=6" } }, - "node_modules/@linaria/logger": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@linaria/logger/-/logger-4.0.0.tgz", - "integrity": "sha512-YnBq0JlDWMEkTOK+tMo5yEVR0f5V//6qMLToGcLhTyM9g9i+IDFn51Z+5q2hLk7RdG4NBPgbcCXYi2w4RKsPeg==", - "dependencies": { - "debug": "^4.1.1", - "picocolors": "^1.0.0" - }, + "node_modules/@babel/register/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, "engines": { - "node": "^12.16.0 || >=13.7.0" + "node": ">=4" } }, - "node_modules/@linaria/tags": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/@linaria/tags/-/tags-4.3.5.tgz", - "integrity": "sha512-PgaIi8Vv89YOjc6rpKL/uPg2w4k0rAwAYxcqeXqzKqsEAste5rgB8xp1/KUOG0oAOkPd3MRL6Duj+m0ZwJ3g+g==", - "dependencies": { - "@babel/generator": "^7.20.4", - "@linaria/logger": "^4.0.0", - "@linaria/utils": "^4.3.4" - }, + "node_modules/@babel/register/node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, "engines": { - "node": "^12.16.0 || >=13.7.0" + "node": ">=6" } }, - "node_modules/@linaria/utils": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/@linaria/utils/-/utils-4.3.4.tgz", - "integrity": "sha512-vt6WJG54n+KANaqxOfzIIU7aSfFHEWFbnGLsgxL7nASHqO0zezrNA2y2Rrp80zSeTW+wSpbmDM4uJyC9UW1qoA==", + "node_modules/@babel/register/node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, "dependencies": { - "@babel/core": "^7.20.2", - "@babel/plugin-proposal-export-namespace-from": "^7.18.9", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-transform-modules-commonjs": "^7.19.6", - "@babel/traverse": "^7.20.1", - "@babel/types": "^7.20.2", - "@linaria/logger": "^4.0.0", - "babel-merge": "^3.0.0" + "find-up": "^3.0.0" }, "engines": { - "node": "^12.16.0 || >=13.7.0" + "node": ">=6" } }, - "node_modules/@loomhq/loom-embed": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@loomhq/loom-embed/-/loom-embed-1.5.0.tgz", - "integrity": "sha512-1Rilv+Ta39Rk2mEb8wzfLSpPhl6ax7kfLNnfYTAGK4mCJIxwQ1o/BY46QRbIpQT/SdfsFCvvNWa57hlEEaduGA==" + "node_modules/@babel/register/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } }, - "node_modules/@nangohq/frontend": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@nangohq/frontend/-/frontend-0.9.0.tgz", - "integrity": "sha512-LLM74Bs1LQ8LalN2zokC/6MEeNMmpGyFAsVTmg5xpeYWXsHG7B1qh4LAUDKWrRM9z9J8r5Y/+hEUv3WJtum1Rw==" + "node_modules/@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", + "dev": true }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "node_modules/@babel/runtime": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz", + "integrity": "sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==", "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" + "regenerator-runtime": "^0.13.11" }, "engines": { - "node": ">= 8" + "node": ">=6.9.0" } }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "node_modules/@babel/template": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" + }, "engines": { - "node": ">= 8" + "node": ">=6.9.0" } }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" + "node_modules/@babel/traverse": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.7.tgz", + "integrity": "sha512-tY3mM8rH9jM0YHFGyfC0/xf+SB5eKUu7HPj7/k3fpi9dAlsMc5YbQvDi0Sh2QTPXqMhyaAtzAr807TIyfQrmyg==", + "dependencies": { + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.6", + "@babel/types": "^7.23.6", + "debug": "^4.3.1", + "globals": "^11.1.0" }, "engines": { - "node": ">= 8" + "node": ">=6.9.0" } }, - "node_modules/@octokit/auth-token": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz", - "integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==", + "node_modules/@babel/types": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.6.tgz", + "integrity": "sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==", "dependencies": { - "@octokit/types": "^6.0.3" + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@octokit/core": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz", - "integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==", - "dependencies": { - "@octokit/auth-token": "^2.4.4", - "@octokit/graphql": "^4.5.8", - "@octokit/request": "^5.6.3", - "@octokit/request-error": "^2.0.5", - "@octokit/types": "^6.0.3", - "before-after-hook": "^2.2.0", - "universal-user-agent": "^6.0.0" + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.1.90" } }, - "node_modules/@octokit/endpoint": { - "version": "6.0.12", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", - "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", - "dependencies": { - "@octokit/types": "^6.0.3", - "is-plain-object": "^5.0.0", - "universal-user-agent": "^6.0.0" + "node_modules/@ctrl/tinycolor": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.0.tgz", + "integrity": "sha512-/Z3l6pXthq0JvMYdUFyX9j0MaCltlIn6mfh9jLyQwg5aPKxkyNa0PTHtU1AlFXLNk55ZuAeJRcpvq+tmLfKmaQ==", + "engines": { + "node": ">=10" } }, - "node_modules/@octokit/graphql": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz", - "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==", + "node_modules/@cubejs-client/core": { + "version": "0.31.63", + "resolved": "https://registry.npmjs.org/@cubejs-client/core/-/core-0.31.63.tgz", + "integrity": "sha512-NFlceV9G2HbFxGqTIjAqS43szRwEJDVzcfuWm/xwlAT6fU4OvZKdDXieKhaxLl38fh64m4VZefej0Mh5jwCmzQ==", "dependencies": { - "@octokit/request": "^5.6.0", - "@octokit/types": "^6.0.3", - "universal-user-agent": "^6.0.0" + "@babel/runtime": "^7.1.2", + "core-js": "^3.6.5", + "cross-fetch": "^3.0.2", + "dayjs": "^1.10.4", + "ramda": "^0.27.2", + "url-search-params-polyfill": "^7.0.0", + "uuid": "^8.3.2" } }, - "node_modules/@octokit/openapi-types": { - "version": "12.11.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", - "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==" - }, - "node_modules/@octokit/request": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz", - "integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==", - "dependencies": { - "@octokit/endpoint": "^6.0.1", - "@octokit/request-error": "^2.1.0", - "@octokit/types": "^6.16.1", - "is-plain-object": "^5.0.0", - "node-fetch": "^2.6.7", - "universal-user-agent": "^6.0.0" + "node_modules/@cubejs-client/core/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" } }, - "node_modules/@octokit/request-error": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", - "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", + "node_modules/@cubejs-client/vue3": { + "version": "0.31.63", + "resolved": "https://registry.npmjs.org/@cubejs-client/vue3/-/vue3-0.31.63.tgz", + "integrity": "sha512-3s2AHzavz6wudNVW7fhBtRsj0LpF6AoBRCzWm0eefMYHqxYK2ShbVEhz+c2oCM8Fri9vt7ZZt4X+70V5iPJTWw==", "dependencies": { - "@octokit/types": "^6.0.3", - "deprecation": "^2.0.0", - "once": "^1.4.0" + "@cubejs-client/core": "^0.31.63", + "@vue/compiler-sfc": "^3.0.11", + "core-js": "^3.6.5", + "flush-promises": "^1.0.2", + "ramda": "^0.27.0", + "vue-loader": "^16.2.0" + }, + "peerDependencies": { + "vue": "^3.0.0" } }, - "node_modules/@octokit/types": { - "version": "6.41.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", - "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", + "node_modules/@cypress/request": { + "version": "2.88.11", + "resolved": "https://registry.npmjs.org/@cypress/request/-/request-2.88.11.tgz", + "integrity": "sha512-M83/wfQ1EkspjkE2lNWNV5ui2Cv7UCv1swW1DqljahbzLVWltcsexQh8jYtuS/vzFXP+HySntGM83ZXA9fn17w==", + "dev": true, "dependencies": { - "@octokit/openapi-types": "^12.11.0" - } - }, - "node_modules/@popperjs/core": { - "name": "@sxzz/popperjs-es", - "version": "2.11.7", - "resolved": "https://registry.npmjs.org/@sxzz/popperjs-es/-/popperjs-es-2.11.7.tgz", - "integrity": "sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/popperjs" + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "http-signature": "~1.3.6", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "performance-now": "^2.1.0", + "qs": "~6.10.3", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^8.3.2" + }, + "engines": { + "node": ">= 6" } }, - "node_modules/@remirror/core-constants": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@remirror/core-constants/-/core-constants-2.0.1.tgz", - "integrity": "sha512-ZR4aihtnnT9lMbhh5DEbsriJRlukRXmLZe7HmM+6ufJNNUDoazc75UX26xbgQlNUqgAqMcUdGFAnPc1JwgAdLQ==", - "dependencies": { - "@babel/runtime": "^7.21.0" - } - }, - "node_modules/@remirror/core-helpers": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@remirror/core-helpers/-/core-helpers-2.0.3.tgz", - "integrity": "sha512-LqIPF4stGG69l9qu/FFicv9d9B+YaItzgDMC5A0CEvDQfKkGD3BfabLmfpnuWbsc06oKGdTduilgWcALLZoYLg==", - "dependencies": { - "@babel/runtime": "^7.21.0", - "@linaria/core": "4.2.9", - "@remirror/core-constants": "^2.0.1", - "@remirror/types": "^1.0.1", - "@types/object.omit": "^3.0.0", - "@types/object.pick": "^1.3.2", - "@types/throttle-debounce": "^2.1.0", - "case-anything": "^2.1.10", - "dash-get": "^1.0.2", - "deepmerge": "^4.3.1", - "fast-deep-equal": "^3.1.3", - "make-error": "^1.3.6", - "object.omit": "^3.0.0", - "object.pick": "^1.3.0", - "throttle-debounce": "^3.0.1" - } - }, - "node_modules/@remirror/types": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@remirror/types/-/types-1.0.1.tgz", - "integrity": "sha512-VlZQxwGnt1jtQ18D6JqdIF+uFZo525WEqrfp9BOc3COPpK4+AWCgdnAWL+ho6imWcoINlGjR/+3b6y5C1vBVEA==", + "node_modules/@cypress/request/node_modules/qs": { + "version": "6.10.4", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.4.tgz", + "integrity": "sha512-OQiU+C+Ds5qiH91qh/mg0w+8nwQuLjM4F4M/PbmhDOoYehPh+Fb0bDjtR1sOvy7YKxvj28Y/M0PhP5uVX0kB+g==", + "dev": true, "dependencies": { - "type-fest": "^2.19.0" - } - }, - "node_modules/@remirror/types/node_modules/type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "side-channel": "^1.0.4" + }, "engines": { - "node": ">=12.20" + "node": ">=0.6" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@rollup/pluginutils": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.2.tgz", - "integrity": "sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==", + "node_modules/@cypress/request/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "dev": true, - "dependencies": { - "@types/estree": "^1.0.0", - "estree-walker": "^2.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } + "bin": { + "uuid": "dist/bin/uuid" } }, - "node_modules/@sideway/address": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz", - "integrity": "sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==", + "node_modules/@cypress/xvfb": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@cypress/xvfb/-/xvfb-1.2.4.tgz", + "integrity": "sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==", "dev": true, "dependencies": { - "@hapi/hoek": "^9.0.0" + "debug": "^3.1.0", + "lodash.once": "^4.1.1" } }, - "node_modules/@sideway/formula": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", - "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==", - "dev": true - }, - "node_modules/@sideway/pinpoint": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", - "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==", - "dev": true - }, - "node_modules/@sinclair/typebox": { - "version": "0.25.24", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.24.tgz", - "integrity": "sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==", - "dev": true + "node_modules/@cypress/xvfb/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } }, - "node_modules/@socket.io/component-emitter": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", - "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" + "node_modules/@dash14/svg-pan-zoom": { + "version": "3.6.9", + "resolved": "https://registry.npmjs.org/@dash14/svg-pan-zoom/-/svg-pan-zoom-3.6.9.tgz", + "integrity": "sha512-6u+KTQec+9+3bRdk2mReix8AGsp2mB40cw0iYfQQzo22QBkeCNpXl2amnfwQzK7xB9oH/62Wvf2z7l6l2w+csA==" }, - "node_modules/@tailwindcss/line-clamp": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/line-clamp/-/line-clamp-0.4.2.tgz", - "integrity": "sha512-HFzAQuqYCjyy/SX9sLGB1lroPzmcnWv1FHkIpmypte10hptf4oPUfucryMKovZh2u0uiS9U5Ty3GghWfEJGwVw==", + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", "dev": true, - "peerDependencies": { - "tailwindcss": ">=2.0.0 || >=3.0.0 || >=3.0.0-alpha.1" + "engines": { + "node": ">=10.0.0" } }, - "node_modules/@tiptap/core": { - "version": "2.1.12", - "resolved": "https://registry.npmjs.org/@tiptap/core/-/core-2.1.12.tgz", - "integrity": "sha512-ZGc3xrBJA9KY8kln5AYTj8y+GDrKxi7u95xIl2eccrqTY5CQeRu6HRNM1yT4mAjuSaG9jmazyjGRlQuhyxCKxQ==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/ueberdosis" - }, + "node_modules/@element-plus/icons-vue": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@element-plus/icons-vue/-/icons-vue-2.1.0.tgz", + "integrity": "sha512-PSBn3elNoanENc1vnCfh+3WA9fimRC7n+fWkf3rE5jvv+aBohNHABC/KAR5KWPecxWxDTVT1ERpRbOMRcOV/vA==", "peerDependencies": { - "@tiptap/pm": "^2.0.0" + "vue": "^3.2.0" } }, - "node_modules/@tiptap/extension-blockquote": { - "version": "2.1.12", - "resolved": "https://registry.npmjs.org/@tiptap/extension-blockquote/-/extension-blockquote-2.1.12.tgz", - "integrity": "sha512-Qb3YRlCfugx9pw7VgLTb+jY37OY4aBJeZnqHzx4QThSm13edNYjasokbX0nTwL1Up4NPTcY19JUeHt6fVaVVGg==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/ueberdosis" - }, + "node_modules/@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz", + "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==", + "dev": true, "peerDependencies": { - "@tiptap/core": "^2.0.0" + "react": ">=16.8.0" } }, - "node_modules/@tiptap/extension-bold": { - "version": "2.1.12", - "resolved": "https://registry.npmjs.org/@tiptap/extension-bold/-/extension-bold-2.1.12.tgz", - "integrity": "sha512-AZGxIxcGU1/y6V2YEbKsq6BAibL8yQrbRm6EdcBnby41vj1WziewEKswhLGmZx5IKM2r2ldxld03KlfSIlKQZg==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/ueberdosis" - }, - "peerDependencies": { - "@tiptap/core": "^2.0.0" + "node_modules/@esbuild/android-arm": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.17.tgz", + "integrity": "sha512-wHsmJG/dnL3OkpAcwbgoBTTMHVi4Uyou3F5mf58ZtmUyIKfcdA7TROav/6tCzET4A3QW2Q2FC+eFneMU+iyOxg==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@tiptap/extension-bubble-menu": { - "version": "2.1.12", - "resolved": "https://registry.npmjs.org/@tiptap/extension-bubble-menu/-/extension-bubble-menu-2.1.12.tgz", - "integrity": "sha512-gAGi21EQ4wvLmT7klgariAc2Hf+cIjaNU2NWze3ut6Ku9gUo5ZLqj1t9SKHmNf4d5JG63O8GxpErqpA7lHlRtw==", - "dependencies": { - "tippy.js": "^6.3.7" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/ueberdosis" - }, - "peerDependencies": { - "@tiptap/core": "^2.0.0", - "@tiptap/pm": "^2.0.0" + "node_modules/@esbuild/android-arm64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.17.tgz", + "integrity": "sha512-9np+YYdNDed5+Jgr1TdWBsozZ85U1Oa3xW0c7TWqH0y2aGghXtZsuT8nYRbzOMcl0bXZXjOGbksoTtVOlWrRZg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@tiptap/extension-bullet-list": { - "version": "2.1.12", - "resolved": "https://registry.npmjs.org/@tiptap/extension-bullet-list/-/extension-bullet-list-2.1.12.tgz", - "integrity": "sha512-vtD8vWtNlmAZX8LYqt2yU9w3mU9rPCiHmbp4hDXJs2kBnI0Ju/qAyXFx6iJ3C3XyuMnMbJdDI9ee0spAvFz7cQ==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/ueberdosis" - }, - "peerDependencies": { - "@tiptap/core": "^2.0.0" + "node_modules/@esbuild/android-x64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.17.tgz", + "integrity": "sha512-O+FeWB/+xya0aLg23hHEM2E3hbfwZzjqumKMSIqcHbNvDa+dza2D0yLuymRBQQnC34CWrsJUXyH2MG5VnLd6uw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@tiptap/extension-code": { - "version": "2.1.12", - "resolved": "https://registry.npmjs.org/@tiptap/extension-code/-/extension-code-2.1.12.tgz", - "integrity": "sha512-CRiRq5OTC1lFgSx6IMrECqmtb93a0ZZKujEnaRhzWliPBjLIi66va05f/P1vnV6/tHaC3yfXys6dxB5A4J8jxw==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/ueberdosis" - }, - "peerDependencies": { - "@tiptap/core": "^2.0.0" + "node_modules/@esbuild/darwin-arm64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.17.tgz", + "integrity": "sha512-M9uJ9VSB1oli2BE/dJs3zVr9kcCBBsE883prage1NWz6pBS++1oNn/7soPNS3+1DGj0FrkSvnED4Bmlu1VAE9g==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@tiptap/extension-code-block": { - "version": "2.1.12", - "resolved": "https://registry.npmjs.org/@tiptap/extension-code-block/-/extension-code-block-2.1.12.tgz", - "integrity": "sha512-RXtSYCVsnk8D+K80uNZShClfZjvv1EgO42JlXLVGWQdIgaNyuOv/6I/Jdf+ZzhnpsBnHufW+6TJjwP5vJPSPHA==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/ueberdosis" - }, - "peerDependencies": { - "@tiptap/core": "^2.0.0", - "@tiptap/pm": "^2.0.0" - } - }, - "node_modules/@tiptap/extension-document": { - "version": "2.1.12", - "resolved": "https://registry.npmjs.org/@tiptap/extension-document/-/extension-document-2.1.12.tgz", - "integrity": "sha512-0QNfAkCcFlB9O8cUNSwTSIQMV9TmoEhfEaLz/GvbjwEq4skXK3bU+OQX7Ih07waCDVXIGAZ7YAZogbvrn/WbOw==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/ueberdosis" - }, - "peerDependencies": { - "@tiptap/core": "^2.0.0" + "node_modules/@esbuild/darwin-x64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.17.tgz", + "integrity": "sha512-XDre+J5YeIJDMfp3n0279DFNrGCXlxOuGsWIkRb1NThMZ0BsrWXoTg23Jer7fEXQ9Ye5QjrvXpxnhzl3bHtk0g==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@tiptap/extension-dropcursor": { - "version": "2.1.12", - "resolved": "https://registry.npmjs.org/@tiptap/extension-dropcursor/-/extension-dropcursor-2.1.12.tgz", - "integrity": "sha512-0tT/q8nL4NBCYPxr9T0Brck+RQbWuczm9nV0bnxgt0IiQXoRHutfPWdS7GA65PTuVRBS/3LOco30fbjFhkfz/A==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/ueberdosis" - }, - "peerDependencies": { - "@tiptap/core": "^2.0.0", - "@tiptap/pm": "^2.0.0" + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.17.tgz", + "integrity": "sha512-cjTzGa3QlNfERa0+ptykyxs5A6FEUQQF0MuilYXYBGdBxD3vxJcKnzDlhDCa1VAJCmAxed6mYhA2KaJIbtiNuQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@tiptap/extension-floating-menu": { - "version": "2.1.12", - "resolved": "https://registry.npmjs.org/@tiptap/extension-floating-menu/-/extension-floating-menu-2.1.12.tgz", - "integrity": "sha512-uo0ydCJNg6AWwLT6cMUJYVChfvw2PY9ZfvKRhh9YJlGfM02jS4RUG/bJBts6R37f+a5FsOvAVwg8EvqPlNND1A==", - "dependencies": { - "tippy.js": "^6.3.7" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/ueberdosis" - }, - "peerDependencies": { - "@tiptap/core": "^2.0.0", - "@tiptap/pm": "^2.0.0" + "node_modules/@esbuild/freebsd-x64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.17.tgz", + "integrity": "sha512-sOxEvR8d7V7Kw8QqzxWc7bFfnWnGdaFBut1dRUYtu+EIRXefBc/eIsiUiShnW0hM3FmQ5Zf27suDuHsKgZ5QrA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@tiptap/extension-gapcursor": { - "version": "2.1.12", - "resolved": "https://registry.npmjs.org/@tiptap/extension-gapcursor/-/extension-gapcursor-2.1.12.tgz", - "integrity": "sha512-zFYdZCqPgpwoB7whyuwpc8EYLYjUE5QYKb8vICvc+FraBUDM51ujYhFSgJC3rhs8EjI+8GcK8ShLbSMIn49YOQ==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/ueberdosis" - }, - "peerDependencies": { - "@tiptap/core": "^2.0.0", - "@tiptap/pm": "^2.0.0" + "node_modules/@esbuild/linux-arm": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.17.tgz", + "integrity": "sha512-2d3Lw6wkwgSLC2fIvXKoMNGVaeY8qdN0IC3rfuVxJp89CRfA3e3VqWifGDfuakPmp90+ZirmTfye1n4ncjv2lg==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@tiptap/extension-hard-break": { - "version": "2.1.12", - "resolved": "https://registry.npmjs.org/@tiptap/extension-hard-break/-/extension-hard-break-2.1.12.tgz", - "integrity": "sha512-nqKcAYGEOafg9D+2cy1E4gHNGuL12LerVa0eS2SQOb+PT8vSel9OTKU1RyZldsWSQJ5rq/w4uIjmLnrSR2w6Yw==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/ueberdosis" - }, - "peerDependencies": { - "@tiptap/core": "^2.0.0" + "node_modules/@esbuild/linux-arm64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.17.tgz", + "integrity": "sha512-c9w3tE7qA3CYWjT+M3BMbwMt+0JYOp3vCMKgVBrCl1nwjAlOMYzEo+gG7QaZ9AtqZFj5MbUc885wuBBmu6aADQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@tiptap/extension-heading": { - "version": "2.1.12", - "resolved": "https://registry.npmjs.org/@tiptap/extension-heading/-/extension-heading-2.1.12.tgz", - "integrity": "sha512-MoANP3POAP68Ko9YXarfDKLM/kXtscgp6m+xRagPAghRNujVY88nK1qBMZ3JdvTVN6b/ATJhp8UdrZX96TLV2w==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/ueberdosis" - }, - "peerDependencies": { - "@tiptap/core": "^2.0.0" + "node_modules/@esbuild/linux-ia32": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.17.tgz", + "integrity": "sha512-1DS9F966pn5pPnqXYz16dQqWIB0dmDfAQZd6jSSpiT9eX1NzKh07J6VKR3AoXXXEk6CqZMojiVDSZi1SlmKVdg==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@tiptap/extension-history": { - "version": "2.1.12", - "resolved": "https://registry.npmjs.org/@tiptap/extension-history/-/extension-history-2.1.12.tgz", - "integrity": "sha512-6b7UFVkvPjq3LVoCTrYZAczt5sQrQUaoDWAieVClVZoFLfjga2Fwjcfgcie8IjdPt8YO2hG/sar/c07i9vM0Sg==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/ueberdosis" - }, - "peerDependencies": { - "@tiptap/core": "^2.0.0", - "@tiptap/pm": "^2.0.0" + "node_modules/@esbuild/linux-loong64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.17.tgz", + "integrity": "sha512-EvLsxCk6ZF0fpCB6w6eOI2Fc8KW5N6sHlIovNe8uOFObL2O+Mr0bflPHyHwLT6rwMg9r77WOAWb2FqCQrVnwFg==", + "cpu": [ + "loong64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@tiptap/extension-horizontal-rule": { - "version": "2.1.12", - "resolved": "https://registry.npmjs.org/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-2.1.12.tgz", - "integrity": "sha512-RRuoK4KxrXRrZNAjJW5rpaxjiP0FJIaqpi7nFbAua2oHXgsCsG8qbW2Y0WkbIoS8AJsvLZ3fNGsQ8gpdliuq3A==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/ueberdosis" - }, - "peerDependencies": { - "@tiptap/core": "^2.0.0", - "@tiptap/pm": "^2.0.0" + "node_modules/@esbuild/linux-mips64el": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.17.tgz", + "integrity": "sha512-e0bIdHA5p6l+lwqTE36NAW5hHtw2tNRmHlGBygZC14QObsA3bD4C6sXLJjvnDIjSKhW1/0S3eDy+QmX/uZWEYQ==", + "cpu": [ + "mips64el" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@tiptap/extension-italic": { - "version": "2.1.12", - "resolved": "https://registry.npmjs.org/@tiptap/extension-italic/-/extension-italic-2.1.12.tgz", - "integrity": "sha512-/XYrW4ZEWyqDvnXVKbgTXItpJOp2ycswk+fJ3vuexyolO6NSs0UuYC6X4f+FbHYL5VuWqVBv7EavGa+tB6sl3A==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/ueberdosis" - }, - "peerDependencies": { - "@tiptap/core": "^2.0.0" + "node_modules/@esbuild/linux-ppc64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.17.tgz", + "integrity": "sha512-BAAilJ0M5O2uMxHYGjFKn4nJKF6fNCdP1E0o5t5fvMYYzeIqy2JdAP88Az5LHt9qBoUa4tDaRpfWt21ep5/WqQ==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@tiptap/extension-link": { - "version": "2.1.12", - "resolved": "https://registry.npmjs.org/@tiptap/extension-link/-/extension-link-2.1.12.tgz", - "integrity": "sha512-Sti5hhlkCqi5vzdQjU/gbmr8kb578p+u0J4kWS+SSz3BknNThEm/7Id67qdjBTOQbwuN07lHjDaabJL0hSkzGQ==", - "dependencies": { - "linkifyjs": "^4.1.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/ueberdosis" - }, - "peerDependencies": { - "@tiptap/core": "^2.0.0", - "@tiptap/pm": "^2.0.0" + "node_modules/@esbuild/linux-riscv64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.17.tgz", + "integrity": "sha512-Wh/HW2MPnC3b8BqRSIme/9Zhab36PPH+3zam5pqGRH4pE+4xTrVLx2+XdGp6fVS3L2x+DrsIcsbMleex8fbE6g==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@tiptap/extension-list-item": { - "version": "2.1.12", - "resolved": "https://registry.npmjs.org/@tiptap/extension-list-item/-/extension-list-item-2.1.12.tgz", - "integrity": "sha512-Gk7hBFofAPmNQ8+uw8w5QSsZOMEGf7KQXJnx5B022YAUJTYYxO3jYVuzp34Drk9p+zNNIcXD4kc7ff5+nFOTrg==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/ueberdosis" - }, - "peerDependencies": { - "@tiptap/core": "^2.0.0" + "node_modules/@esbuild/linux-s390x": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.17.tgz", + "integrity": "sha512-j/34jAl3ul3PNcK3pfI0NSlBANduT2UO5kZ7FCaK33XFv3chDhICLY8wJJWIhiQ+YNdQ9dxqQctRg2bvrMlYgg==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@tiptap/extension-ordered-list": { - "version": "2.1.12", - "resolved": "https://registry.npmjs.org/@tiptap/extension-ordered-list/-/extension-ordered-list-2.1.12.tgz", - "integrity": "sha512-tF6VGl+D2avCgn9U/2YLJ8qVmV6sPE/iEzVAFZuOSe6L0Pj7SQw4K6AO640QBob/d8VrqqJFHCb6l10amJOnXA==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/ueberdosis" - }, - "peerDependencies": { - "@tiptap/core": "^2.0.0" + "node_modules/@esbuild/linux-x64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.17.tgz", + "integrity": "sha512-QM50vJ/y+8I60qEmFxMoxIx4de03pGo2HwxdBeFd4nMh364X6TIBZ6VQ5UQmPbQWUVWHWws5MmJXlHAXvJEmpQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@tiptap/extension-paragraph": { - "version": "2.1.12", - "resolved": "https://registry.npmjs.org/@tiptap/extension-paragraph/-/extension-paragraph-2.1.12.tgz", - "integrity": "sha512-hoH/uWPX+KKnNAZagudlsrr4Xu57nusGekkJWBcrb5MCDE91BS+DN2xifuhwXiTHxnwOMVFjluc0bPzQbkArsw==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/ueberdosis" - }, - "peerDependencies": { - "@tiptap/core": "^2.0.0" + "node_modules/@esbuild/netbsd-x64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.17.tgz", + "integrity": "sha512-/jGlhWR7Sj9JPZHzXyyMZ1RFMkNPjC6QIAan0sDOtIo2TYk3tZn5UDrkE0XgsTQCxWTTOcMPf9p6Rh2hXtl5TQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@tiptap/extension-placeholder": { - "version": "2.1.12", - "resolved": "https://registry.npmjs.org/@tiptap/extension-placeholder/-/extension-placeholder-2.1.12.tgz", - "integrity": "sha512-K52o7B1zkP4vaVy3z4ZwHn+tQy6KlXtedj1skLg+796ImwH2GYS5z6MFOTfKzBO2hLncUzLco/s0C5PLCD6SDw==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/ueberdosis" - }, - "peerDependencies": { - "@tiptap/core": "^2.0.0", - "@tiptap/pm": "^2.0.0" + "node_modules/@esbuild/openbsd-x64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.17.tgz", + "integrity": "sha512-rSEeYaGgyGGf4qZM2NonMhMOP/5EHp4u9ehFiBrg7stH6BYEEjlkVREuDEcQ0LfIl53OXLxNbfuIj7mr5m29TA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@tiptap/extension-strike": { - "version": "2.1.12", - "resolved": "https://registry.npmjs.org/@tiptap/extension-strike/-/extension-strike-2.1.12.tgz", - "integrity": "sha512-HlhrzIjYUT8oCH9nYzEL2QTTn8d1ECnVhKvzAe6x41xk31PjLMHTUy8aYjeQEkWZOWZ34tiTmslV1ce6R3Dt8g==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/ueberdosis" - }, - "peerDependencies": { - "@tiptap/core": "^2.0.0" + "node_modules/@esbuild/sunos-x64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.17.tgz", + "integrity": "sha512-Y7ZBbkLqlSgn4+zot4KUNYst0bFoO68tRgI6mY2FIM+b7ZbyNVtNbDP5y8qlu4/knZZ73fgJDlXID+ohY5zt5g==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@tiptap/extension-text": { - "version": "2.1.12", - "resolved": "https://registry.npmjs.org/@tiptap/extension-text/-/extension-text-2.1.12.tgz", - "integrity": "sha512-rCNUd505p/PXwU9Jgxo4ZJv4A3cIBAyAqlx/dtcY6cjztCQuXJhuQILPhjGhBTOLEEL4kW2wQtqzCmb7O8i2jg==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/ueberdosis" - }, - "peerDependencies": { - "@tiptap/core": "^2.0.0" + "node_modules/@esbuild/win32-arm64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.17.tgz", + "integrity": "sha512-bwPmTJsEQcbZk26oYpc4c/8PvTY3J5/QK8jM19DVlEsAB41M39aWovWoHtNm78sd6ip6prilxeHosPADXtEJFw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@tiptap/pm": { - "version": "2.1.12", - "resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-2.1.12.tgz", - "integrity": "sha512-Q3MXXQABG4CZBesSp82yV84uhJh/W0Gag6KPm2HRWPimSFELM09Z9/5WK9RItAYE0aLhe4Krnyiczn9AAa1tQQ==", - "dependencies": { - "prosemirror-changeset": "^2.2.0", - "prosemirror-collab": "^1.3.0", - "prosemirror-commands": "^1.3.1", - "prosemirror-dropcursor": "^1.5.0", - "prosemirror-gapcursor": "^1.3.1", - "prosemirror-history": "^1.3.0", - "prosemirror-inputrules": "^1.2.0", - "prosemirror-keymap": "^1.2.0", - "prosemirror-markdown": "^1.10.1", - "prosemirror-menu": "^1.2.1", - "prosemirror-model": "^1.18.1", - "prosemirror-schema-basic": "^1.2.0", - "prosemirror-schema-list": "^1.2.2", - "prosemirror-state": "^1.4.1", - "prosemirror-tables": "^1.3.0", - "prosemirror-trailing-node": "^2.0.2", - "prosemirror-transform": "^1.7.0", - "prosemirror-view": "^1.28.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/ueberdosis" + "node_modules/@esbuild/win32-ia32": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.17.tgz", + "integrity": "sha512-H/XaPtPKli2MhW+3CQueo6Ni3Avggi6hP/YvgkEe1aSaxw+AeO8MFjq8DlgfTd9Iz4Yih3QCZI6YLMoyccnPRg==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@tiptap/starter-kit": { - "version": "2.1.12", - "resolved": "https://registry.npmjs.org/@tiptap/starter-kit/-/starter-kit-2.1.12.tgz", - "integrity": "sha512-+RoP1rWV7rSCit2+3wl2bjvSRiePRJE/7YNKbvH8Faz/+AMO23AFegHoUFynR7U0ouGgYDljGkkj35e0asbSDA==", - "dependencies": { - "@tiptap/core": "^2.1.12", - "@tiptap/extension-blockquote": "^2.1.12", - "@tiptap/extension-bold": "^2.1.12", - "@tiptap/extension-bullet-list": "^2.1.12", - "@tiptap/extension-code": "^2.1.12", - "@tiptap/extension-code-block": "^2.1.12", - "@tiptap/extension-document": "^2.1.12", - "@tiptap/extension-dropcursor": "^2.1.12", - "@tiptap/extension-gapcursor": "^2.1.12", - "@tiptap/extension-hard-break": "^2.1.12", - "@tiptap/extension-heading": "^2.1.12", - "@tiptap/extension-history": "^2.1.12", - "@tiptap/extension-horizontal-rule": "^2.1.12", - "@tiptap/extension-italic": "^2.1.12", - "@tiptap/extension-list-item": "^2.1.12", - "@tiptap/extension-ordered-list": "^2.1.12", - "@tiptap/extension-paragraph": "^2.1.12", - "@tiptap/extension-strike": "^2.1.12", - "@tiptap/extension-text": "^2.1.12" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/ueberdosis" + "node_modules/@esbuild/win32-x64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.17.tgz", + "integrity": "sha512-fGEb8f2BSA3CW7riJVurug65ACLuQAzKq0SSqkY2b2yHHH0MzDfbLyKIGzHwOI/gkHcxM/leuSW6D5w/LMNitA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@tiptap/vue-3": { - "version": "2.1.12", - "resolved": "https://registry.npmjs.org/@tiptap/vue-3/-/vue-3-2.1.12.tgz", - "integrity": "sha512-yAcfmWw/9jtIUbhb0uGQVI9NoPYgHRasX2sAGWnm9Al+0aJktgmQ3mLCifXfXfjyEbeMF0p2L6Ul8tO7eho7aQ==", + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", "dependencies": { - "@tiptap/extension-bubble-menu": "^2.1.12", - "@tiptap/extension-floating-menu": "^2.1.12" + "eslint-visitor-keys": "^3.3.0" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/ueberdosis" + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "peerDependencies": { - "@tiptap/core": "^2.0.0", - "@tiptap/pm": "^2.0.0", - "vue": "^3.0.0" + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@trysound/sax": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", - "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", - "dev": true, + "node_modules/@eslint-community/regexpp": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.4.1.tgz", + "integrity": "sha512-BISJ6ZE4xQsuL/FmsyRaiffpq977bMlsKfGHTQrOGFErfByxIe6iZTxPf/00Zon9b9a7iUykfQwejN3s2ZW/Bw==", "engines": { - "node": ">=10.13.0" + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/@types/eslint": { - "version": "8.21.3", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.21.3.tgz", - "integrity": "sha512-fa7GkppZVEByMWGbTtE5MbmXWJTVbrjjaS8K6uQj+XtuuUv1fsuPAxhygfqLmsb/Ufb3CV8deFCpiMfAgi00Sw==", - "peer": true, + "node_modules/@eslint/eslintrc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.1.tgz", + "integrity": "sha512-eFRmABvW2E5Ho6f5fHLqgena46rOj7r7OKHYfLElqcBfGFHHpjBhivyi5+jOEQuSpdc/1phIZJlbC2te+tZNIw==", "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint-scope": { - "version": "3.7.4", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", - "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", - "peer": true, + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.5.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@types/estree": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz", - "integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==" + "node_modules/@eslint/eslintrc/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "node_modules/@eslint/js": { + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.36.0.tgz", + "integrity": "sha512-lxJ9R5ygVm8ZWgYdUweoq5ownDlJ4upvoWmO4eLxBYHdMo+vZ/Rx0EN6MbKWDJOSUGrqJy2Gt+Dyv/VKml0fjg==", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@fal-works/esbuild-plugin-global-externals": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@fal-works/esbuild-plugin-global-externals/-/esbuild-plugin-global-externals-2.1.2.tgz", + "integrity": "sha512-cEee/Z+I12mZcFJshKcCqC8tuX5hG3s+d+9nZ3LabqKF1vKdF41B92pJVCBggjAGORAeOzyyDDKrZwIkLffeOQ==", "dev": true }, - "node_modules/@types/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", - "dev": true, + "node_modules/@floating-ui/core": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.5.3.tgz", + "integrity": "sha512-O0WKDOo0yhJuugCx6trZQj5jVJ9yR0ystG2JaNAemYUWce+pmM6WUEFIibnWyEJKdrDxhm75NoSRME35FNaM/Q==", "dependencies": { - "@types/istanbul-lib-coverage": "*" + "@floating-ui/utils": "^0.2.0" } }, - "node_modules/@types/istanbul-reports": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", - "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", - "dev": true, + "node_modules/@floating-ui/dom": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.5.4.tgz", + "integrity": "sha512-jByEsHIY+eEdCjnTVu+E3ephzTOzkQ8hgUfGwos+bg7NlH33Zc5uO+QHz1mrQUOgIKKDD1RtS201P9NvAfq3XQ==", "dependencies": { - "@types/istanbul-lib-report": "*" + "@floating-ui/core": "^1.5.3", + "@floating-ui/utils": "^0.2.0" } }, - "node_modules/@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==" - }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==" - }, - "node_modules/@types/lodash": { - "version": "4.14.191", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.191.tgz", - "integrity": "sha512-BdZ5BCCvho3EIXw6wUCXHe7rS53AIDPLE+JzwgT+OsJk53oBfbSmZZ7CX4VaRoN78N+TJpFi9QPlfIVNmJYWxQ==" - }, - "node_modules/@types/lodash-es": { - "version": "4.17.7", - "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.7.tgz", - "integrity": "sha512-z0ptr6UI10VlU6l5MYhGwS4mC8DZyYer2mCoyysZtSF7p26zOX8UpbrV0YpNYLGS8K4PUFIyEr62IMFFjveSiQ==", + "node_modules/@floating-ui/react-dom": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.0.6.tgz", + "integrity": "sha512-IB8aCRFxr8nFkdYZgH+Otd9EVQPJoynxeFRGTB8voPoZMRWo8XjYuCRgpI1btvuKY69XMiLnW+ym7zoBHM90Rw==", + "dev": true, "dependencies": { - "@types/lodash": "*" + "@floating-ui/dom": "^1.5.4" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" } }, - "node_modules/@types/node": { - "version": "14.18.41", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.41.tgz", - "integrity": "sha512-2cfHr8AsUjKx6u4Q+d2eqK51z8+HueoumCQGCKVt95y/yGG4uajOuCANSnE20mbLw94h3tMcddIJ8nYkTu2mFw==" - }, - "node_modules/@types/object.omit": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/object.omit/-/object.omit-3.0.0.tgz", - "integrity": "sha512-I27IoPpH250TUzc9FzXd0P1BV/BMJuzqD3jOz98ehf9dQqGkxlq+hO1bIqZGWqCg5bVOy0g4AUVJtnxe0klDmw==" - }, - "node_modules/@types/object.pick": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@types/object.pick/-/object.pick-1.3.2.tgz", - "integrity": "sha512-sn7L+qQ6RLPdXRoiaE7bZ/Ek+o4uICma/lBFPyJEKDTPTBP1W8u0c4baj3EiS4DiqLs+Hk+KUGvMVJtAw3ePJg==" - }, - "node_modules/@types/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", - "dev": true + "node_modules/@floating-ui/utils": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.1.tgz", + "integrity": "sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q==" }, - "node_modules/@types/sinonjs__fake-timers": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz", - "integrity": "sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g==", - "dev": true + "node_modules/@formbricks/js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@formbricks/js/-/js-1.2.0.tgz", + "integrity": "sha512-bhQutlEHWnMHm54h6tc2VRM8lj/Rio0tT1L+zNjFv0Hcx4TamZ/967MyhGpY0LnJyqdr8Ck/+DtEWFSAOO5HEw==" }, - "node_modules/@types/sizzle": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz", - "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==", + "node_modules/@hapi/hoek": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", + "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==", "dev": true }, - "node_modules/@types/throttle-debounce": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@types/throttle-debounce/-/throttle-debounce-2.1.0.tgz", - "integrity": "sha512-5eQEtSCoESnh2FsiLTxE121IiE60hnMqcb435fShf4bpLRjEu1Eoekht23y6zXS9Ts3l+Szu3TARnTsA0GkOkQ==" - }, - "node_modules/@types/web-bluetooth": { - "version": "0.0.16", - "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz", - "integrity": "sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==" - }, - "node_modules/@types/yargs": { - "version": "17.0.23", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.23.tgz", - "integrity": "sha512-yuogunc04OnzGQCrfHx+Kk883Q4X0aSwmYZhKjI21m+SVYzjIbrWl8dOOwSv5hf2Um2pdCOXWo9isteZTNXUZQ==", + "node_modules/@hapi/topo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", "dev": true, "dependencies": { - "@types/yargs-parser": "*" + "@hapi/hoek": "^9.0.0" } }, - "node_modules/@types/yargs-parser": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", - "dev": true - }, - "node_modules/@types/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==", - "dev": true, - "optional": true, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", + "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", "dependencies": { - "@types/node": "*" + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" } }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.59.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.5.tgz", - "integrity": "sha512-feA9xbVRWJZor+AnLNAr7A8JRWeZqHUf4T9tlP+TN04b05pFVhO5eN7/O93Y/1OUlLMHKbnJisgDURs/qvtqdg==", - "dev": true, - "dependencies": { - "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.59.5", - "@typescript-eslint/type-utils": "5.59.5", - "@typescript-eslint/utils": "5.59.5", - "debug": "^4.3.4", - "grapheme-splitter": "^1.0.4", - "ignore": "^5.2.0", - "natural-compare-lite": "^1.4.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=12.22" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==" + }, + "node_modules/@interactjs/actions": { + "version": "1.10.17", + "resolved": "https://registry.npmjs.org/@interactjs/actions/-/actions-1.10.17.tgz", + "integrity": "sha512-wyB1ZqpaZy5gmz6VDqK9KWh98xKnFgL7VyLvxHODFi9V0IYX4HJAAOBlhtfze0D1R1f1cY+gqPDK+dLaHMlE+w==", + "optionalDependencies": { + "@interactjs/interact": "1.10.17" }, "peerDependencies": { - "@typescript-eslint/parser": "^5.0.0", - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + "@interactjs/core": "1.10.17", + "@interactjs/utils": "1.10.17" + } + }, + "node_modules/@interactjs/auto-scroll": { + "version": "1.10.17", + "resolved": "https://registry.npmjs.org/@interactjs/auto-scroll/-/auto-scroll-1.10.17.tgz", + "integrity": "sha512-IQcW7N3xOaoL8RnAGOGMk0Y2gue7L4S3BT6Id4VBBu8so163DtLiZVW6jXu9rKVntzbluaAeqNZlfAVyu3kIWg==", + "optionalDependencies": { + "@interactjs/interact": "1.10.17" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "peerDependencies": { + "@interactjs/utils": "1.10.17" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" + "node_modules/@interactjs/auto-start": { + "version": "1.10.17", + "resolved": "https://registry.npmjs.org/@interactjs/auto-start/-/auto-start-1.10.17.tgz", + "integrity": "sha512-qYVxhAbYnwxjD/NLEegUoAST7WASJ4VmWNjsyWRx/js5Op+I4E2zteARIeZGgrutcGIXMCcQzhCMgE3PjOpbpw==", + "optionalDependencies": { + "@interactjs/interact": "1.10.17" }, - "engines": { - "node": ">=10" + "peerDependencies": { + "@interactjs/core": "1.10.17", + "@interactjs/utils": "1.10.17" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==", - "dev": true, + "node_modules/@interactjs/core": { + "version": "1.10.17", + "resolved": "https://registry.npmjs.org/@interactjs/core/-/core-1.10.17.tgz", + "integrity": "sha512-rL9w+83HDRuXub8Ezqs+97CYLl/ne7bLT/sAeduUWaxYhsW9iOqBoob9JnkkCZOaOsYizWI1EWy0+fNc5ibtLQ==", + "peerDependencies": { + "@interactjs/utils": "1.10.17" + } + }, + "node_modules/@interactjs/dev-tools": { + "version": "1.10.17", + "resolved": "https://registry.npmjs.org/@interactjs/dev-tools/-/dev-tools-1.10.17.tgz", + "integrity": "sha512-Oi9nEw3FfSwkNmW+V0WwdHqvzEkVHc24mH1v5EjRn60sqgrGLK9nTQ+NSuqcnUY8GxC3TkyuxnsOodxiadIRmA==", + "optionalDependencies": { + "@interactjs/interact": "1.10.17" + }, + "peerDependencies": { + "@interactjs/modifiers": "1.10.17", + "@interactjs/utils": "1.10.17" + } + }, + "node_modules/@interactjs/inertia": { + "version": "1.10.17", + "resolved": "https://registry.npmjs.org/@interactjs/inertia/-/inertia-1.10.17.tgz", + "integrity": "sha512-41vbYUjZIDCKt2/yhmjPrEW5+0uoL/hldFsll9pkvnLhmm12Xk0VXOlmR2zXKAmsTK3fJlKMyBYUX92qHLkyVQ==", "dependencies": { - "lru-cache": "^6.0.0" + "@interactjs/offset": "1.10.17" }, - "bin": { - "semver": "bin/semver.js" + "optionalDependencies": { + "@interactjs/interact": "1.10.17" }, - "engines": { - "node": ">=10" + "peerDependencies": { + "@interactjs/core": "1.10.17", + "@interactjs/modifiers": "1.10.17", + "@interactjs/utils": "1.10.17" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "node_modules/@interactjs/interact": { + "version": "1.10.17", + "resolved": "https://registry.npmjs.org/@interactjs/interact/-/interact-1.10.17.tgz", + "integrity": "sha512-NyKsf8EFudvdahBjPz1Gt5QnynVwa/2LUfBc2/w8QOnOBiyzUm0HLloJSaB8a50QbQkSWN243/Lgpd8GTMQvuQ==", + "dependencies": { + "@interactjs/core": "1.10.17", + "@interactjs/types": "1.10.17", + "@interactjs/utils": "1.10.17" + } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, + "node_modules/@interactjs/interactjs": { + "version": "1.10.17", + "resolved": "https://registry.npmjs.org/@interactjs/interactjs/-/interactjs-1.10.17.tgz", + "integrity": "sha512-hHmiukARbZhiM12zNKx0yQlFVl4C+NMeYNAYh6Mf9U3ZziQ47C+JEW8Gr7Zr/MxfNZyPu5nLKCpVQjh/JvBO9g==", "dependencies": { - "tslib": "^1.8.1" + "@interactjs/actions": "1.10.17", + "@interactjs/auto-scroll": "1.10.17", + "@interactjs/auto-start": "1.10.17", + "@interactjs/core": "1.10.17", + "@interactjs/dev-tools": "1.10.17", + "@interactjs/inertia": "1.10.17", + "@interactjs/interact": "1.10.17", + "@interactjs/modifiers": "1.10.17", + "@interactjs/offset": "1.10.17", + "@interactjs/pointer-events": "1.10.17", + "@interactjs/reflow": "1.10.17", + "@interactjs/utils": "1.10.17" + } + }, + "node_modules/@interactjs/modifiers": { + "version": "1.10.17", + "resolved": "https://registry.npmjs.org/@interactjs/modifiers/-/modifiers-1.10.17.tgz", + "integrity": "sha512-Dxw8kv9VBIxnhNvQncR6CKAGMzKXczLvuAUIdSPFYtyerX/XiDulJUqhR+jVKNp/WjF1DvdBxWo0kGGLbM84LQ==", + "dependencies": { + "@interactjs/snappers": "1.10.17" }, - "engines": { - "node": ">= 6" + "optionalDependencies": { + "@interactjs/interact": "1.10.17" }, "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + "@interactjs/core": "1.10.17", + "@interactjs/utils": "1.10.17" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/@typescript-eslint/parser": { - "version": "5.59.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.5.tgz", - "integrity": "sha512-NJXQC4MRnF9N9yWqQE2/KLRSOLvrrlZb48NGVfBa+RuPMN6B7ZcK5jZOvhuygv4D64fRKnZI4L4p8+M+rfeQuw==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "5.59.5", - "@typescript-eslint/types": "5.59.5", - "@typescript-eslint/typescript-estree": "5.59.5", - "debug": "^4.3.4" + "node_modules/@interactjs/offset": { + "version": "1.10.17", + "resolved": "https://registry.npmjs.org/@interactjs/offset/-/offset-1.10.17.tgz", + "integrity": "sha512-wWBnIQWgLrmJNTBbd/FdxHxAJjiXl/5ND8Jbw2DuP9gIGDxhFSdEt62Fgqimn9ICb8v8ycvSLObEmcvJF/8hQQ==", + "optionalDependencies": { + "@interactjs/interact": "1.10.17" }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "peerDependencies": { + "@interactjs/core": "1.10.17", + "@interactjs/utils": "1.10.17" + } + }, + "node_modules/@interactjs/pointer-events": { + "version": "1.10.17", + "resolved": "https://registry.npmjs.org/@interactjs/pointer-events/-/pointer-events-1.10.17.tgz", + "integrity": "sha512-VsfluouEKb8QRGyH6jQATCW+QdAd/3dkENS7rj2m+EcVUhz2Ob5mpMRopjALi4pwltMowqTfuJ4LtwMSX2G29A==", + "optionalDependencies": { + "@interactjs/interact": "1.10.17" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "peerDependencies": { + "@interactjs/core": "1.10.17", + "@interactjs/utils": "1.10.17" + } + }, + "node_modules/@interactjs/reflow": { + "version": "1.10.17", + "resolved": "https://registry.npmjs.org/@interactjs/reflow/-/reflow-1.10.17.tgz", + "integrity": "sha512-ncpWP5k93FRQptEhjzPZsbuRRajd4rkW17lDavCrEjrDi/LHnYekWGqZTaFzfJ80n1x8xUm9ujDjxCTylNqEIA==", + "optionalDependencies": { + "@interactjs/interact": "1.10.17" }, "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + "@interactjs/core": "1.10.17", + "@interactjs/utils": "1.10.17" + } + }, + "node_modules/@interactjs/snappers": { + "version": "1.10.17", + "resolved": "https://registry.npmjs.org/@interactjs/snappers/-/snappers-1.10.17.tgz", + "integrity": "sha512-m753DGsNOts797e3zDT6wqELoc+BlpIC1w+TyMyISRxU6n1RlS8Q6LHBGgwAgV79LHLaahv/a5haFF9H1VG0FQ==", + "optionalDependencies": { + "@interactjs/interact": "1.10.17" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "peerDependencies": { + "@interactjs/utils": "1.10.17" } }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "5.59.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.5.tgz", - "integrity": "sha512-jVecWwnkX6ZgutF+DovbBJirZcAxgxC0EOHYt/niMROf8p4PwxxG32Qdhj/iIQQIuOflLjNkxoXyArkcIP7C3A==", + "node_modules/@interactjs/types": { + "version": "1.10.17", + "resolved": "https://registry.npmjs.org/@interactjs/types/-/types-1.10.17.tgz", + "integrity": "sha512-X2JpoM7xUw0p9Me0tMaI0HNfcF/Hd07ZZlzpnpEMpGerUZOLoyeThrV9P+CrBHxZrluWJrigJbcdqXliFd0YMA==" + }, + "node_modules/@interactjs/utils": { + "version": "1.10.17", + "resolved": "https://registry.npmjs.org/@interactjs/utils/-/utils-1.10.17.tgz", + "integrity": "sha512-sZAW08CkqgvqRjUIaLRjScjObcCzN9D75yekLA21EClYAZIhi4A+GEt2z/WqOCOksTaEPLYmQyhkpXcboc0LhQ==" + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.5", - "@typescript-eslint/visitor-keys": "5.59.5" + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/@typescript-eslint/type-utils": { - "version": "5.59.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.5.tgz", - "integrity": "sha512-4eyhS7oGym67/pSxA2mmNq7X164oqDYNnZCUayBwJZIRVvKpBCMBzFnFxjeoDeShjtO6RQBHBuwybuX3POnDqg==", + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, - "dependencies": { - "@typescript-eslint/typescript-estree": "5.59.5", - "@typescript-eslint/utils": "5.59.5", - "debug": "^4.3.4", - "tsutils": "^3.21.0" - }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=12" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "*" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/@typescript-eslint/type-utils/node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dev": true, "dependencies": { - "tslib": "^1.8.1" + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" }, "engines": { - "node": ">= 6" + "node": ">=12" }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@typescript-eslint/types": { - "version": "5.59.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.5.tgz", - "integrity": "sha512-xkfRPHbqSH4Ggx4eHRIO/eGL8XL4Ysb4woL8c87YuAo8Md7AUjyWKa9YMwTL519SyDPrfEgKdewjkxNCVeJW7w==", + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=12" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.59.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.5.tgz", - "integrity": "sha512-+XXdLN2CZLZcD/mO7mQtJMvCkzRfmODbeSKuMY/yXbGkzvA9rJyDY5qDYNoiz2kP/dmyAxXquL2BvLQLJFPQIg==", + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.5", - "@typescript-eslint/visitor-keys": "5.59.5", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=12" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", "dev": true, "dependencies": { - "yallist": "^4.0.0" + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" }, "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" }, "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "dependencies": { - "tslib": "^1.8.1" + "p-locate": "^4.1.0" }, "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + "node": ">=8" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/@typescript-eslint/utils": { - "version": "5.59.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.5.tgz", - "integrity": "sha512-sCEHOiw+RbyTii9c3/qN74hYDPNORb8yWCoPLmB7BIflhplJ65u2PBpdRla12e3SSTJ2erRkPjz7ngLHhUegxA==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.59.5", - "@typescript-eslint/types": "5.59.5", - "@typescript-eslint/typescript-estree": "5.59.5", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" + "p-try": "^2.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=6" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@typescript-eslint/utils/node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" + "p-limit": "^2.2.0" }, "engines": { - "node": ">=8.0.0" + "node": ">=8" } }, - "node_modules/@typescript-eslint/utils/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, "engines": { - "node": ">=4.0" + "node": ">=8" } }, - "node_modules/@typescript-eslint/utils/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dev": true, "dependencies": { - "yallist": "^4.0.0" + "@sinclair/typebox": "^0.27.8" }, "engines": { - "node": ">=10" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@typescript-eslint/utils/node_modules/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==", + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", "dev": true, "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" }, "engines": { - "node": ">=10" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@typescript-eslint/utils/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.59.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.5.tgz", - "integrity": "sha512-qL+Oz+dbeBRTeyJTIy0eniD3uvqU7x+y1QceBismZ41hd4aBSRh8UAw4pZP0+XzLuPZmx4raNMq/I+59W2lXKA==", + "node_modules/@jest/transform/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.5", - "eslint-visitor-keys": "^3.3.0" + "color-convert": "^2.0.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=8" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@vitejs/plugin-vue": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-4.2.3.tgz", - "integrity": "sha512-R6JDUfiZbJA9cMiguQ7jxALsgiprjBeHL5ikpXfJCH62pPHtI+JdJ5xWj6Ev73yXSlYl86+blXn1kZHQ7uElxw==", + "node_modules/@jest/transform/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": "^14.18.0 || >=16.0.0" + "node": ">=10" }, - "peerDependencies": { - "vite": "^4.0.0", - "vue": "^3.2.25" - } - }, - "node_modules/@vue/compiler-core": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.3.1.tgz", - "integrity": "sha512-5le1qYSBgLWg2jdLrbydlhnPJkkzMw46UrRUvTnOKlfg6pThtm9ohhqBhNPHbr0RcM1MCbK5WZe/3Ghz0SZjpQ==", - "dependencies": { - "@babel/parser": "^7.21.3", - "@vue/shared": "3.3.1", - "estree-walker": "^2.0.2", - "source-map-js": "^1.0.2" + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@vue/compiler-dom": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.3.1.tgz", - "integrity": "sha512-VmgIsoLivCft3+oNc5KM7b9wd0nZxP/g2qilMwi1hJyGA624KWnNKHn4hzBQs4FpzydUVpNy+TWVT8KiRCh3MQ==", + "node_modules/@jest/transform/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { - "@vue/compiler-core": "3.3.1", - "@vue/shared": "3.3.1" + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "node_modules/@vue/compiler-sfc": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.3.1.tgz", - "integrity": "sha512-G+FPwBbXSLaA4+Ry5/bdD9Oda+sRslQcE9o6JSZaougRiT4OjVL0vtkbQHPrGRTULZV28OcrAjRfSZOSB0OTXQ==", - "dependencies": { - "@babel/parser": "^7.20.15", - "@vue/compiler-core": "3.3.1", - "@vue/compiler-dom": "3.3.1", - "@vue/compiler-ssr": "3.3.1", - "@vue/reactivity-transform": "3.3.1", - "@vue/shared": "3.3.1", - "estree-walker": "^2.0.2", - "magic-string": "^0.30.0", - "postcss": "^8.1.10", - "source-map-js": "^1.0.2" - } + "node_modules/@jest/transform/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, - "node_modules/@vue/compiler-ssr": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.3.1.tgz", - "integrity": "sha512-QOQWGNCWuSeyKx4KvWSJlnIMGg+/2oCHgkFUYo7aJ+9Uaaz45yRgKQ+FNigy50NYBQIhpXn2e4OSR8GXh4knrQ==", - "dependencies": { - "@vue/compiler-dom": "3.3.1", - "@vue/shared": "3.3.1" + "node_modules/@jest/transform/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/@vue/devtools-api": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.5.0.tgz", - "integrity": "sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q==" - }, - "node_modules/@vue/eslint-config-airbnb": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@vue/eslint-config-airbnb/-/eslint-config-airbnb-7.0.0.tgz", - "integrity": "sha512-qC3HRnvaDWRocDKPVKUnjWLXo1NDfDSPKwizc49llN/mRZF2Q9D/7wcAMwzCVzPM/D80ZUz0sy1cq9u/6jFnqw==", + "node_modules/@jest/transform/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { - "eslint-config-airbnb-base": "^15.0.0", - "eslint-import-resolver-custom-alias": "^1.3.0", - "eslint-import-resolver-node": "^0.3.6", - "eslint-plugin-import": "^2.26.0", - "eslint-plugin-jsx-a11y": "^6.6.1", - "eslint-plugin-react": "^7.30.1", - "eslint-plugin-vuejs-accessibility": "^1.2.0", - "vue-eslint-parser": "^9.0.3" + "has-flag": "^4.0.0" }, - "peerDependencies": { - "eslint": "^8.2.0", - "eslint-plugin-vue": "^9.2.0" + "engines": { + "node": ">=8" } }, - "node_modules/@vue/eslint-config-typescript": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/@vue/eslint-config-typescript/-/eslint-config-typescript-11.0.3.tgz", - "integrity": "sha512-dkt6W0PX6H/4Xuxg/BlFj5xHvksjpSlVjtkQCpaYJBIEuKj2hOVU7r+TIe+ysCwRYFz/lGqvklntRkCAibsbPw==", + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", "dev": true, "dependencies": { - "@typescript-eslint/eslint-plugin": "^5.59.1", - "@typescript-eslint/parser": "^5.59.1", - "vue-eslint-parser": "^9.1.1" + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" }, "engines": { - "node": "^14.17.0 || >=16.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" }, - "peerDependencies": { - "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0", - "eslint-plugin-vue": "^9.0.0", - "typescript": "*" + "engines": { + "node": ">=8" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@vue/reactivity": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.3.1.tgz", - "integrity": "sha512-zCfmazOtyUdC1NS/EPiSYJ4RqojqmTAviJyBbyVvY8zAv5NhK44Yfw0E1tt+m5vz0ZO1ptI9jDKBr3MWIEkpgw==", + "node_modules/@jest/types/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { - "@vue/shared": "3.3.1" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@vue/reactivity-transform": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.3.1.tgz", - "integrity": "sha512-MkOrJauAGH4MNdxGW/PmrDegMyOGX0wGIdKUZJRBXOTpotDONg7/TPJe2QeGeBCow/5v9iOqZOWCfvmOWIaDMg==", + "node_modules/@jest/types/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { - "@babel/parser": "^7.20.15", - "@vue/compiler-core": "3.3.1", - "@vue/shared": "3.3.1", - "estree-walker": "^2.0.2", - "magic-string": "^0.30.0" + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "node_modules/@vue/runtime-core": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.3.1.tgz", - "integrity": "sha512-Ljb37LYafhQqKIasc0r32Cva8gIh6VeSMjlwO6V03tCjHd18gmjP0F4UD+8/a59sGTysAgA8Rb9lIC2DVxRz2Q==", - "dependencies": { - "@vue/reactivity": "3.3.1", - "@vue/shared": "3.3.1" + "node_modules/@jest/types/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/types/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/@vue/runtime-dom": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.3.1.tgz", - "integrity": "sha512-NBjYbQPtMklb7lsJsM2Juv5Ygry6mvZP7PdH1GZqrzfLkvlplQT3qCtQMd/sib6yiy8t9m/Y4hVU7X9nzb9Oeg==", + "node_modules/@jest/types/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { - "@vue/runtime-core": "3.3.1", - "@vue/shared": "3.3.1", - "csstype": "^3.1.1" + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@vue/server-renderer": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.3.1.tgz", - "integrity": "sha512-sod8ggOwbkQXw3lBjfzrbdxRS9lw/lNHoMaXghHawNYowf+4WoaLWD5ouz6fPZadUqNKAsqK95p8DYb1vcVfPA==", + "node_modules/@jridgewell/gen-mapping": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", + "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", "dependencies": { - "@vue/compiler-ssr": "3.3.1", - "@vue/shared": "3.3.1" + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10" }, - "peerDependencies": { - "vue": "3.3.1" + "engines": { + "node": ">=6.0.0" } }, - "node_modules/@vue/shared": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.3.1.tgz", - "integrity": "sha512-ybDBtQ+479HL/bkeIOIAwgpeAEACzztkvulJLbK3JMFuTOv4qDivmV3AIsR8RHYJ+RD9tQxcHWBsX4GqEcYrfw==" + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "engines": { + "node": ">=6.0.0" + } }, - "node_modules/@vuelidate/core": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@vuelidate/core/-/core-2.0.1.tgz", - "integrity": "sha512-seBfM7ZtQ+NzXEdJpwLPgX/GlY+R10VI3FSoXyEJH7p4kKcz06f5oloh2EDozCJVMxP0Um/FFcfjBCn8CtGNOQ==", + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", + "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", "dependencies": { - "vue-demi": "^0.13.11" - }, - "peerDependencies": { - "@vue/composition-api": "^1.0.0-rc.1", - "vue": "^2.0.0 || >=3.0.0" - }, - "peerDependenciesMeta": { - "@vue/composition-api": { - "optional": true - } + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" } }, - "node_modules/@vuelidate/core/node_modules/vue-demi": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.11.tgz", - "integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==", - "hasInstallScript": true, - "bin": { - "vue-demi-fix": "bin/vue-demi-fix.js", - "vue-demi-switch": "bin/vue-demi-switch.js" + "node_modules/@jridgewell/source-map/node_modules/@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - }, - "peerDependencies": { - "@vue/composition-api": "^1.0.0-rc.1", - "vue": "^3.0.0-0 || ^2.6.0" - }, - "peerDependenciesMeta": { - "@vue/composition-api": { - "optional": true - } + "node": ">=6.0.0" } }, - "node_modules/@vuelidate/validators": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@vuelidate/validators/-/validators-2.0.1.tgz", - "integrity": "sha512-rlu14xo+r36ri2VMY6kLLgzIc3RKEIEKiyq/Nwvft3h8izt6jcBqOlDPkQL1d9qxn9mr2nVBcNlMBFMDrHpp/A==", + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.22", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz", + "integrity": "sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==", "dependencies": { - "vue-demi": "^0.13.11" - }, - "peerDependencies": { - "@vue/composition-api": "^1.0.0-rc.1", - "vue": "^2.0.0 || >=3.0.0" - }, - "peerDependenciesMeta": { - "@vue/composition-api": { - "optional": true - } + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@vuelidate/validators/node_modules/vue-demi": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.11.tgz", - "integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==", - "hasInstallScript": true, - "bin": { - "vue-demi-fix": "bin/vue-demi-fix.js", - "vue-demi-switch": "bin/vue-demi-switch.js" + "node_modules/@juggle/resize-observer": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@juggle/resize-observer/-/resize-observer-3.4.0.tgz", + "integrity": "sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==", + "dev": true + }, + "node_modules/@koa/router": { + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/@koa/router/-/router-9.4.0.tgz", + "integrity": "sha512-dOOXgzqaDoHu5qqMEPLKEgLz5CeIA7q8+1W62mCvFVCOqeC71UoTGJ4u1xUSOpIl2J1x2pqrNULkFteUeZW3/A==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "http-errors": "^1.7.3", + "koa-compose": "^4.1.0", + "methods": "^1.1.2", + "path-to-regexp": "^6.1.0" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - }, - "peerDependencies": { - "@vue/composition-api": "^1.0.0-rc.1", - "vue": "^3.0.0-0 || ^2.6.0" - }, - "peerDependenciesMeta": { - "@vue/composition-api": { - "optional": true - } + "node": ">= 8.0.0" } }, - "node_modules/@vueuse/core": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-9.13.0.tgz", - "integrity": "sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==", + "node_modules/@linaria/core": { + "version": "4.2.9", + "resolved": "https://registry.npmjs.org/@linaria/core/-/core-4.2.9.tgz", + "integrity": "sha512-ELcu37VNVOT/PU0L6WDIN+aLzNFyJrqoBYT0CucGOCAmODbojUMCv8oJYRbWzA3N34w1t199dN4UFdfRWFG2rg==", "dependencies": { - "@types/web-bluetooth": "^0.0.16", - "@vueuse/metadata": "9.13.0", - "@vueuse/shared": "9.13.0", - "vue-demi": "*" + "@linaria/logger": "^4.0.0", + "@linaria/tags": "^4.3.4", + "@linaria/utils": "^4.3.3" }, - "funding": { - "url": "https://github.com/sponsors/antfu" + "engines": { + "node": "^12.16.0 || >=13.7.0" } }, - "node_modules/@vueuse/core/node_modules/vue-demi": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.11.tgz", - "integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==", - "hasInstallScript": true, - "bin": { - "vue-demi-fix": "bin/vue-demi-fix.js", - "vue-demi-switch": "bin/vue-demi-switch.js" + "node_modules/@linaria/logger": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@linaria/logger/-/logger-4.0.0.tgz", + "integrity": "sha512-YnBq0JlDWMEkTOK+tMo5yEVR0f5V//6qMLToGcLhTyM9g9i+IDFn51Z+5q2hLk7RdG4NBPgbcCXYi2w4RKsPeg==", + "dependencies": { + "debug": "^4.1.1", + "picocolors": "^1.0.0" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - }, - "peerDependencies": { - "@vue/composition-api": "^1.0.0-rc.1", - "vue": "^3.0.0-0 || ^2.6.0" - }, - "peerDependenciesMeta": { - "@vue/composition-api": { - "optional": true - } - } - }, - "node_modules/@vueuse/metadata": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-9.13.0.tgz", - "integrity": "sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==", - "funding": { - "url": "https://github.com/sponsors/antfu" + "node": "^12.16.0 || >=13.7.0" } }, - "node_modules/@vueuse/shared": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-9.13.0.tgz", - "integrity": "sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==", + "node_modules/@linaria/tags": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/@linaria/tags/-/tags-4.3.5.tgz", + "integrity": "sha512-PgaIi8Vv89YOjc6rpKL/uPg2w4k0rAwAYxcqeXqzKqsEAste5rgB8xp1/KUOG0oAOkPd3MRL6Duj+m0ZwJ3g+g==", "dependencies": { - "vue-demi": "*" + "@babel/generator": "^7.20.4", + "@linaria/logger": "^4.0.0", + "@linaria/utils": "^4.3.4" }, - "funding": { - "url": "https://github.com/sponsors/antfu" + "engines": { + "node": "^12.16.0 || >=13.7.0" } }, - "node_modules/@vueuse/shared/node_modules/vue-demi": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.11.tgz", - "integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==", - "hasInstallScript": true, - "bin": { - "vue-demi-fix": "bin/vue-demi-fix.js", - "vue-demi-switch": "bin/vue-demi-switch.js" + "node_modules/@linaria/utils": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/@linaria/utils/-/utils-4.3.4.tgz", + "integrity": "sha512-vt6WJG54n+KANaqxOfzIIU7aSfFHEWFbnGLsgxL7nASHqO0zezrNA2y2Rrp80zSeTW+wSpbmDM4uJyC9UW1qoA==", + "dependencies": { + "@babel/core": "^7.20.2", + "@babel/plugin-proposal-export-namespace-from": "^7.18.9", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-transform-modules-commonjs": "^7.19.6", + "@babel/traverse": "^7.20.1", + "@babel/types": "^7.20.2", + "@linaria/logger": "^4.0.0", + "babel-merge": "^3.0.0" }, "engines": { - "node": ">=12" + "node": "^12.16.0 || >=13.7.0" + } + }, + "node_modules/@loomhq/loom-embed": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@loomhq/loom-embed/-/loom-embed-1.5.0.tgz", + "integrity": "sha512-1Rilv+Ta39Rk2mEb8wzfLSpPhl6ax7kfLNnfYTAGK4mCJIxwQ1o/BY46QRbIpQT/SdfsFCvvNWa57hlEEaduGA==" + }, + "node_modules/@mdx-js/react": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-2.3.0.tgz", + "integrity": "sha512-zQH//gdOmuu7nt2oJR29vFhDv88oGPmVw6BggmrHeMI+xgEkp1B2dX9/bMBSYtK0dyLX/aOmesKS09g222K1/g==", + "dev": true, + "dependencies": { + "@types/mdx": "^2.0.0", + "@types/react": ">=16" }, "funding": { - "url": "https://github.com/sponsors/antfu" + "type": "opencollective", + "url": "https://opencollective.com/unified" }, "peerDependencies": { - "@vue/composition-api": "^1.0.0-rc.1", - "vue": "^3.0.0-0 || ^2.6.0" - }, - "peerDependenciesMeta": { - "@vue/composition-api": { - "optional": true - } + "react": ">=16" } }, - "node_modules/@webassemblyjs/ast": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", - "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", - "peer": true, + "node_modules/@nangohq/frontend": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@nangohq/frontend/-/frontend-0.9.0.tgz", + "integrity": "sha512-LLM74Bs1LQ8LalN2zokC/6MEeNMmpGyFAsVTmg5xpeYWXsHG7B1qh4LAUDKWrRM9z9J8r5Y/+hEUv3WJtum1Rw==" + }, + "node_modules/@ndelangen/get-tarball": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@ndelangen/get-tarball/-/get-tarball-3.0.9.tgz", + "integrity": "sha512-9JKTEik4vq+yGosHYhZ1tiH/3WpUS0Nh0kej4Agndhox8pAdWhEx5knFVRcb/ya9knCRCs1rPxNrSXTDdfVqpA==", + "dev": true, "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + "gunzip-maybe": "^1.4.2", + "pump": "^3.0.0", + "tar-fs": "^2.1.1" } }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", - "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", - "peer": true - }, - "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", - "peer": true - }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", - "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==", - "peer": true - }, - "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", - "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", - "peer": true, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", - "@xtuc/long": "4.2.2" + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" } }, - "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", - "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", - "peer": true - }, - "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", - "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", - "peer": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6" + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "engines": { + "node": ">= 8" } }, - "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", - "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", - "peer": true, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dependencies": { - "@xtuc/ieee754": "^1.2.0" + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" } }, - "node_modules/@webassemblyjs/leb128": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", - "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", - "peer": true, + "node_modules/@octokit/auth-token": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz", + "integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==", "dependencies": { - "@xtuc/long": "4.2.2" + "@octokit/types": "^6.0.3" } }, - "node_modules/@webassemblyjs/utf8": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", - "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", - "peer": true - }, - "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", - "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", - "peer": true, + "node_modules/@octokit/core": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz", + "integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==", "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/helper-wasm-section": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6", - "@webassemblyjs/wasm-opt": "1.11.6", - "@webassemblyjs/wasm-parser": "1.11.6", - "@webassemblyjs/wast-printer": "1.11.6" + "@octokit/auth-token": "^2.4.4", + "@octokit/graphql": "^4.5.8", + "@octokit/request": "^5.6.3", + "@octokit/request-error": "^2.0.5", + "@octokit/types": "^6.0.3", + "before-after-hook": "^2.2.0", + "universal-user-agent": "^6.0.0" } }, - "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", - "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", - "peer": true, + "node_modules/@octokit/endpoint": { + "version": "6.0.12", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", + "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" + "@octokit/types": "^6.0.3", + "is-plain-object": "^5.0.0", + "universal-user-agent": "^6.0.0" } }, - "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", - "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", - "peer": true, + "node_modules/@octokit/graphql": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz", + "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==", "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6", - "@webassemblyjs/wasm-parser": "1.11.6" + "@octokit/request": "^5.6.0", + "@octokit/types": "^6.0.3", + "universal-user-agent": "^6.0.0" } }, - "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", - "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", - "peer": true, + "node_modules/@octokit/openapi-types": { + "version": "12.11.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", + "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==" + }, + "node_modules/@octokit/request": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz", + "integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==", "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" + "@octokit/endpoint": "^6.0.1", + "@octokit/request-error": "^2.1.0", + "@octokit/types": "^6.16.1", + "is-plain-object": "^5.0.0", + "node-fetch": "^2.6.7", + "universal-user-agent": "^6.0.0" } }, - "node_modules/@webassemblyjs/wast-printer": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", - "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", - "peer": true, + "node_modules/@octokit/request-error": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", + "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@xtuc/long": "4.2.2" + "@octokit/types": "^6.0.3", + "deprecation": "^2.0.0", + "once": "^1.4.0" } }, - "node_modules/@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "peer": true - }, - "node_modules/@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "peer": true - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dev": true, + "node_modules/@octokit/types": { + "version": "6.41.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", + "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" + "@octokit/openapi-types": "^12.11.0" } }, - "node_modules/acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", - "bin": { - "acorn": "bin/acorn" - }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, "engines": { - "node": ">=0.4.0" + "node": ">=14" } }, - "node_modules/acorn-import-assertions": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", - "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", - "peer": true, - "peerDependencies": { - "acorn": "^8" + "node_modules/@popperjs/core": { + "name": "@sxzz/popperjs-es", + "version": "2.11.7", + "resolved": "https://registry.npmjs.org/@sxzz/popperjs-es/-/popperjs-es-2.11.7.tgz", + "integrity": "sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" } }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + "node_modules/@radix-ui/number": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.0.1.tgz", + "integrity": "sha512-T5gIdVO2mmPW3NNhjNgEP3cqMXjXL9UbO0BzWcXfvdBs+BohbQxvd/K5hSVKmn9/lbTdsQVKbUcP5WLCwvUbBg==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.13.10" } }, - "node_modules/acorn-node": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", - "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", + "node_modules/@radix-ui/primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.0.1.tgz", + "integrity": "sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw==", "dev": true, "dependencies": { - "acorn": "^7.0.0", - "acorn-walk": "^7.0.0", - "xtend": "^4.0.2" + "@babel/runtime": "^7.13.10" } }, - "node_modules/acorn-node/node_modules/acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "node_modules/@radix-ui/react-arrow": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.0.3.tgz", + "integrity": "sha512-wSP+pHsB/jQRaL6voubsQ/ZlrGBHHrOjmBnr19hxYgtS0WvAFwZhK2WP/YY5yF9uKECCEEDGxuLxq1NBK51wFA==", "dev": true, - "bin": { - "acorn": "bin/acorn" + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-primitive": "1.0.3" }, - "engines": { - "node": ">=0.4.0" + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/acorn-node/node_modules/acorn-walk": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", - "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "node_modules/@radix-ui/react-collection": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.0.3.tgz", + "integrity": "sha512-3SzW+0PW7yBBoQlT8wNcGtaxaD0XSu0uLUFgrtHY08Acx05TaHaOmVLR73c0j/cqpDy53KBMO7s0dx2wmOIDIA==", "dev": true, - "engines": { - "node": ">=0.4.0" + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-slot": "1.0.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "node_modules/@radix-ui/react-compose-refs": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.1.tgz", + "integrity": "sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==", "dev": true, "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" + "@babel/runtime": "^7.13.10" }, - "engines": { - "node": ">=8" + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "node_modules/@radix-ui/react-context": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.0.1.tgz", + "integrity": "sha512-ebbrdFoYTcuZ0v4wG5tedGnp9tzcV8awzsxYph7gXUyvnNLuTIcCk1q17JEbnVhXAKG9oX3KtchwiMIAYp9NLg==", + "dev": true, "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "@babel/runtime": "^7.13.10" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "node_modules/@radix-ui/react-direction": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.0.1.tgz", + "integrity": "sha512-RXcvnXgyvYvBEOhCBuddKecVkoMiI10Jcm5cTI7abJRAHYfFxeu+FBQs/DvdxSYucxR5mna0dNsL6QFlds5TMA==", "dev": true, "dependencies": { - "ajv": "^8.0.0" + "@babel/runtime": "^7.13.10" }, "peerDependencies": { - "ajv": "^8.0.0" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" }, "peerDependenciesMeta": { - "ajv": { + "@types/react": { "optional": true } } }, - "node_modules/ajv-formats/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.4.tgz", + "integrity": "sha512-7UpBa/RKMoHJYjie1gkF1DlK8l1fdU/VKDpoS3rCCo8YBJR294GwcEHyxHw72yvphJ7ld0AXEcSLAzY2F/WyCg==", "dev": true, "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-callback-ref": "1.0.1", + "@radix-ui/react-use-escape-keydown": "1.0.3" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-formats/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", "peerDependencies": { - "ajv": "^6.9.1" + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "node_modules/@radix-ui/react-focus-guards": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.0.1.tgz", + "integrity": "sha512-Rect2dWbQ8waGzhMavsIbmSVCgYxkXLxxR3ZvCX79JOglzdEy4JXMb98lq4hPxUbLr77nP0UOGf4rcMU+s1pUA==", "dev": true, - "engines": { - "node": ">=6" + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "node_modules/@radix-ui/react-focus-scope": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.3.tgz", + "integrity": "sha512-upXdPfqI4islj2CslyfUBNlaJCPybbqRHAi1KER7Isel9Q2AtSJ0zRBZv8mWQiFXD2nyAJ4BhC3yXgZ6kMBSrQ==", "dev": true, "dependencies": { - "type-fest": "^0.21.3" + "@babel/runtime": "^7.13.10", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-callback-ref": "1.0.1" }, - "engines": { - "node": ">=8" + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "node_modules/@radix-ui/react-id": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.0.1.tgz", + "integrity": "sha512-tI7sT/kqYp8p96yGWY1OAnLHrqDgzHefRBKQ2YAkBS5ja7QLcZ9Z/uY7bEjPUatf8RomoXM8/1sMj1IJaE5UzQ==", + "dev": true, "dependencies": { - "color-convert": "^1.9.0" + "@babel/runtime": "^7.13.10", + "@radix-ui/react-use-layout-effect": "1.0.1" }, - "engines": { - "node": ">=4" + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "devOptional": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" + "node_modules/@radix-ui/react-popper": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.1.2.tgz", + "integrity": "sha512-1CnGGfFi/bbqtJZZ0P/NQY20xdG3E0LALJaLUEoKwPLwl6PPPfbeiCqMVQnhoFRAxjJj4RpBRJzDmUgsex2tSg==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.13.10", + "@floating-ui/react-dom": "^2.0.0", + "@radix-ui/react-arrow": "1.0.3", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-callback-ref": "1.0.1", + "@radix-ui/react-use-layout-effect": "1.0.1", + "@radix-ui/react-use-rect": "1.0.1", + "@radix-ui/react-use-size": "1.0.1", + "@radix-ui/rect": "1.0.1" }, - "engines": { - "node": ">= 8" + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/arch": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", - "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", + "node_modules/@radix-ui/react-portal": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.0.3.tgz", + "integrity": "sha512-xLYZeHrWoPmA5mEKEfZZevoVRK/Q43GfzRXkWV6qawIWWK8t6ifIiLQdd7rmQ4Vk1bmI21XhqF9BN3jWf+phpA==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-primitive": "1.0.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true }, - { - "type": "consulting", - "url": "https://feross.org/support" + "@types/react-dom": { + "optional": true } - ] - }, - "node_modules/arg": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", - "dev": true - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + } }, - "node_modules/aria-query": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", - "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", + "node_modules/@radix-ui/react-primitive": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-1.0.3.tgz", + "integrity": "sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==", + "dev": true, "dependencies": { - "deep-equal": "^2.0.5" + "@babel/runtime": "^7.13.10", + "@radix-ui/react-slot": "1.0.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "node_modules/@radix-ui/react-roving-focus": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.0.4.tgz", + "integrity": "sha512-2mUg5Mgcu001VkGy+FfzZyzbmuUWzgWkj3rvv4yu+mLw03+mTzbxZHvfcGyFp2b8EkQeMkpRQ5FiA2Vr2O6TeQ==", + "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-collection": "1.0.3", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-direction": "1.0.1", + "@radix-ui/react-id": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-callback-ref": "1.0.1", + "@radix-ui/react-use-controllable-state": "1.0.1" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/array-includes": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", - "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", + "node_modules/@radix-ui/react-select": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-1.2.2.tgz", + "integrity": "sha512-zI7McXr8fNaSrUY9mZe4x/HC0jTLY9fWNhO1oLWYMQGDXuV4UCivIGTxwioSzO0ZCYX9iSLyWmAh/1TOmX3Cnw==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/number": "1.0.1", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-collection": "1.0.3", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-direction": "1.0.1", + "@radix-ui/react-dismissable-layer": "1.0.4", + "@radix-ui/react-focus-guards": "1.0.1", + "@radix-ui/react-focus-scope": "1.0.3", + "@radix-ui/react-id": "1.0.1", + "@radix-ui/react-popper": "1.1.2", + "@radix-ui/react-portal": "1.0.3", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-slot": "1.0.2", + "@radix-ui/react-use-callback-ref": "1.0.1", + "@radix-ui/react-use-controllable-state": "1.0.1", + "@radix-ui/react-use-layout-effect": "1.0.1", + "@radix-ui/react-use-previous": "1.0.1", + "@radix-ui/react-visually-hidden": "1.0.3", + "aria-hidden": "^1.1.1", + "react-remove-scroll": "2.5.5" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-separator": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.0.3.tgz", + "integrity": "sha512-itYmTy/kokS21aiV5+Z56MZB54KrhPgn6eHDKkFeOLR34HMN2s8PaN47qZZAGnvupcjxHaFZnW4pQEh0BvvVuw==", + "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.3", - "is-string": "^1.0.7" + "@babel/runtime": "^7.13.10", + "@radix-ui/react-primitive": "1.0.3" }, - "engines": { - "node": ">= 0.4" + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "node_modules/@radix-ui/react-slot": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz", + "integrity": "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==", "dev": true, - "engines": { - "node": ">=8" + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-compose-refs": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/array.prototype.flat": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", - "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", + "node_modules/@radix-ui/react-toggle": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-toggle/-/react-toggle-1.0.3.tgz", + "integrity": "sha512-Pkqg3+Bc98ftZGsl60CLANXQBBQ4W3mTFS9EJvNxKMZ7magklKV69/id1mlAlOFDDfHvlCms0fx8fA4CMKDJHg==", + "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0" + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-controllable-state": "1.0.1" }, - "engines": { - "node": ">= 0.4" + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", - "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", + "node_modules/@radix-ui/react-toggle-group": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-toggle-group/-/react-toggle-group-1.0.4.tgz", + "integrity": "sha512-Uaj/M/cMyiyT9Bx6fOZO0SAG4Cls0GptBWiBmBxofmDbNVnYYoyRWj/2M/6VCi/7qcXFWnHhRUfdfZFvvkuu8A==", + "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0" + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-direction": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-roving-focus": "1.0.4", + "@radix-ui/react-toggle": "1.0.3", + "@radix-ui/react-use-controllable-state": "1.0.1" }, - "engines": { - "node": ">= 0.4" + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/array.prototype.tosorted": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.1.tgz", - "integrity": "sha512-pZYPXPRl2PqWcsUs6LOMn+1f1532nEoPTYowBtqLwAW+W8vSVhkIGnmOX1t/UQjD6YGI0vcD2B1U7ZFGQH9jnQ==", + "node_modules/@radix-ui/react-toolbar": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-toolbar/-/react-toolbar-1.0.4.tgz", + "integrity": "sha512-tBgmM/O7a07xbaEkYJWYTXkIdU/1pW4/KZORR43toC/4XWyBCURK0ei9kMUdp+gTPPKBgYLxXmRSH1EVcIDp8Q==", + "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0", - "get-intrinsic": "^1.1.3" + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-direction": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-roving-focus": "1.0.4", + "@radix-ui/react-separator": "1.0.3", + "@radix-ui/react-toggle-group": "1.0.4" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/asn1": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "node_modules/@radix-ui/react-use-callback-ref": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.1.tgz", + "integrity": "sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ==", "dev": true, "dependencies": { - "safer-buffer": "~2.1.0" + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.0.1.tgz", + "integrity": "sha512-Svl5GY5FQeN758fWKrjM6Qb7asvXeiZltlT4U2gVfl8Gx5UAv2sMR0LWo8yhsIZh2oQ0eFdZ59aoOOMV7b47VA==", "dev": true, - "engines": { - "node": ">=0.8" + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-use-callback-ref": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/ast-types-flow": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", - "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==" + "node_modules/@radix-ui/react-use-escape-keydown": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.0.3.tgz", + "integrity": "sha512-vyL82j40hcFicA+M4Ex7hVkB9vHgSse1ZWomAqV2Je3RleKGO5iM8KMOEtfoSB0PnIelMd2lATjTGMYqN5ylTg==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-use-callback-ref": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } }, - "node_modules/astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.0.1.tgz", + "integrity": "sha512-v/5RegiJWYdoCvMnITBkNNx6bCj20fiaJnWtRkU18yITptraXjffz5Qbn05uOiQnOvi+dbkznkoaMltz1GnszQ==", "dev": true, - "engines": { - "node": ">=8" + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/async": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", - "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", - "dev": true - }, - "node_modules/async-validator": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-4.2.5.tgz", - "integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==" - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true - }, - "node_modules/at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "node_modules/@radix-ui/react-use-previous": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.0.1.tgz", + "integrity": "sha512-cV5La9DPwiQ7S0gf/0qiD6YgNqM5Fk97Kdrlc5yBcrF3jyEZQwm7vYFqMo4IfeHgJXsRaMvLABFtd0OVEmZhDw==", "dev": true, - "engines": { - "node": ">= 4.0.0" + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/autoprefixer": { - "version": "10.4.14", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.14.tgz", - "integrity": "sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ==", + "node_modules/@radix-ui/react-use-rect": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.0.1.tgz", + "integrity": "sha512-Cq5DLuSiuYVKNU8orzJMbl15TXilTnJKUCltMVQg53BQOF1/C5toAaGrowkgksdBQ9H+SRL23g0HDmg9tvmxXw==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/autoprefixer" - } - ], "dependencies": { - "browserslist": "^4.21.5", - "caniuse-lite": "^1.0.30001464", - "fraction.js": "^4.2.0", - "normalize-range": "^0.1.2", - "picocolors": "^1.0.0", - "postcss-value-parser": "^4.2.0" + "@babel/runtime": "^7.13.10", + "@radix-ui/rect": "1.0.1" }, - "bin": { - "autoprefixer": "bin/autoprefixer" + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" }, - "engines": { - "node": "^10 || ^12 || >=14" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-size": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.0.1.tgz", + "integrity": "sha512-ibay+VqrgcaI6veAojjofPATwledXiSmX+C0KrBk/xgpX9rBzPV3OsfwlhQdUOFbh+LKQorLYT+xTXW9V8yd0g==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-use-layout-effect": "1.0.1" }, "peerDependencies": { - "postcss": "^8.1.0" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", - "engines": { - "node": ">= 0.4" + "node_modules/@radix-ui/react-visually-hidden": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.0.3.tgz", + "integrity": "sha512-D4w41yN5YRKtu464TLnByKzMDG/JlMPHtfZgQAu9v6mNakUqGUI9vUrfQKz8NK41VMm/xbZbh76NUTVtIYqOMA==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-primitive": "1.0.3" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", + "node_modules/@radix-ui/rect": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.0.1.tgz", + "integrity": "sha512-fyrgCaedtvMg9NK3en0pnOYJdtfwxUcNolezkNPUsoX57X8oQk+NkqcvzHXD2uKNij6GXmWU9NDru2IWjrO4BQ==", "dev": true, - "engines": { - "node": "*" + "dependencies": { + "@babel/runtime": "^7.13.10" } }, - "node_modules/aws4": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", - "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==", - "dev": true - }, - "node_modules/axe-core": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.6.3.tgz", - "integrity": "sha512-/BQzOX780JhsxDnPpH4ZiyrJAzcd8AfzFPkv+89veFSr1rcMjuq2JDCwypKaPeB6ljHp9KjXhPpjgCvQlWYuqg==", - "engines": { - "node": ">=4" + "node_modules/@remirror/core-constants": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@remirror/core-constants/-/core-constants-2.0.1.tgz", + "integrity": "sha512-ZR4aihtnnT9lMbhh5DEbsriJRlukRXmLZe7HmM+6ufJNNUDoazc75UX26xbgQlNUqgAqMcUdGFAnPc1JwgAdLQ==", + "dependencies": { + "@babel/runtime": "^7.21.0" } }, - "node_modules/axios": { - "version": "0.22.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.22.0.tgz", - "integrity": "sha512-Z0U3uhqQeg1oNcihswf4ZD57O3NrR1+ZXhxaROaWpDmsDTx7T2HNBV2ulBtie2hwJptu8UvgnJoK+BIqdzh/1w==", + "node_modules/@remirror/core-helpers": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@remirror/core-helpers/-/core-helpers-2.0.3.tgz", + "integrity": "sha512-LqIPF4stGG69l9qu/FFicv9d9B+YaItzgDMC5A0CEvDQfKkGD3BfabLmfpnuWbsc06oKGdTduilgWcALLZoYLg==", "dependencies": { - "follow-redirects": "^1.14.4" + "@babel/runtime": "^7.21.0", + "@linaria/core": "4.2.9", + "@remirror/core-constants": "^2.0.1", + "@remirror/types": "^1.0.1", + "@types/object.omit": "^3.0.0", + "@types/object.pick": "^1.3.2", + "@types/throttle-debounce": "^2.1.0", + "case-anything": "^2.1.10", + "dash-get": "^1.0.2", + "deepmerge": "^4.3.1", + "fast-deep-equal": "^3.1.3", + "make-error": "^1.3.6", + "object.omit": "^3.0.0", + "object.pick": "^1.3.0", + "throttle-debounce": "^3.0.1" } }, - "node_modules/axobject-query": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz", - "integrity": "sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==", + "node_modules/@remirror/types": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@remirror/types/-/types-1.0.1.tgz", + "integrity": "sha512-VlZQxwGnt1jtQ18D6JqdIF+uFZo525WEqrfp9BOc3COPpK4+AWCgdnAWL+ho6imWcoINlGjR/+3b6y5C1vBVEA==", "dependencies": { - "deep-equal": "^2.0.5" + "type-fest": "^2.19.0" } }, - "node_modules/babel-merge": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/babel-merge/-/babel-merge-3.0.0.tgz", - "integrity": "sha512-eBOBtHnzt9xvnjpYNI5HmaPp/b2vMveE5XggzqHnQeHJ8mFIBrBv6WZEVIj5jJ2uwTItkqKo9gWzEEcBxEq0yw==", + "node_modules/@remirror/types/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@rollup/pluginutils": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.2.tgz", + "integrity": "sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==", + "dev": true, "dependencies": { - "deepmerge": "^2.2.1", - "object.omit": "^3.0.0" + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" }, "peerDependencies": { - "@babel/core": "^7.0.0" + "rollup": "^1.20.0||^2.0.0||^3.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } } }, - "node_modules/babel-merge/node_modules/deepmerge": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz", - "integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==", - "engines": { - "node": ">=0.10.0" + "node_modules/@sideway/address": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz", + "integrity": "sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==", + "dev": true, + "dependencies": { + "@hapi/hoek": "^9.0.0" } }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + "node_modules/@sideway/formula": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", + "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==", + "dev": true }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] + "node_modules/@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==", + "dev": true }, - "node_modules/batch-processor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/batch-processor/-/batch-processor-1.0.0.tgz", - "integrity": "sha512-xoLQD8gmmR32MeuBHgH0Tzd5PuSZx71ZsbhVxOCRbgktZEPe4SQy7s9Z50uPp0F/f7iw2XmkHN2xkgbMfckMDA==" + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true }, - "node_modules/bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "node_modules/@socket.io/component-emitter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", + "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" + }, + "node_modules/@storybook/addon-actions": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-7.6.10.tgz", + "integrity": "sha512-pcKmf0H/caGzKDy8cz1adNSjv+KOBWLJ11RzGExrWm+Ad5ACifwlsQPykJ3TQ/21sTd9IXVrE9uuq4LldEnPbg==", "dev": true, "dependencies": { - "tweetnacl": "^0.14.3" + "@storybook/core-events": "7.6.10", + "@storybook/global": "^5.0.0", + "@types/uuid": "^9.0.1", + "dequal": "^2.0.2", + "polished": "^4.2.2", + "uuid": "^9.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" } }, - "node_modules/before-after-hook": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", - "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==" + "node_modules/@storybook/addon-actions/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } }, - "node_modules/big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "engines": { - "node": "*" - } - }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "devOptional": true, - "engines": { - "node": ">=8" + "node_modules/@storybook/addon-backgrounds": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/addon-backgrounds/-/addon-backgrounds-7.6.10.tgz", + "integrity": "sha512-kGzsN1QkfyI8Cz7TErEx9OCB3PMzpCFGLd/iy7FreXwbMbeAQ3/9fYgKUsNOYgOhuTz7S09koZUWjS/WJuZGFA==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0", + "memoizerific": "^1.11.3", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" } }, - "node_modules/blob-util": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz", - "integrity": "sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==", - "dev": true - }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true - }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/@storybook/addon-controls": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/addon-controls/-/addon-controls-7.6.10.tgz", + "integrity": "sha512-LjwCQRMWq1apLtFwDi6U8MI6ITUr+KhxJucZ60tfc58RgB2v8ayozyDAonFEONsx9YSR1dNIJ2Z/e2rWTBJeYA==", + "dev": true, "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "@storybook/blocks": "7.6.10", + "lodash": "^4.17.21", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/addon-docs": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-7.6.10.tgz", + "integrity": "sha512-GtyQ9bMx1AOOtl6ZS9vwK104HFRK+tqzxddRRxhXkpyeKu3olm9aMgXp35atE/3fJSqyyDm2vFtxxH8mzBA20A==", + "dev": true, + "dependencies": { + "@jest/transform": "^29.3.1", + "@mdx-js/react": "^2.1.5", + "@storybook/blocks": "7.6.10", + "@storybook/client-logger": "7.6.10", + "@storybook/components": "7.6.10", + "@storybook/csf-plugin": "7.6.10", + "@storybook/csf-tools": "7.6.10", + "@storybook/global": "^5.0.0", + "@storybook/mdx2-csf": "^1.0.0", + "@storybook/node-logger": "7.6.10", + "@storybook/postinstall": "7.6.10", + "@storybook/preview-api": "7.6.10", + "@storybook/react-dom-shim": "7.6.10", + "@storybook/theming": "7.6.10", + "@storybook/types": "7.6.10", + "fs-extra": "^11.1.0", + "remark-external-links": "^8.0.0", + "remark-slug": "^6.0.0", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "devOptional": true, + "node_modules/@storybook/addon-docs/node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dev": true, "dependencies": { - "fill-range": "^7.0.1" + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, "engines": { - "node": ">=8" + "node": ">=14.14" } }, - "node_modules/browserslist": { - "version": "4.21.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", - "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - } - ], + "node_modules/@storybook/addon-essentials": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/addon-essentials/-/addon-essentials-7.6.10.tgz", + "integrity": "sha512-cjbuCCK/3dtUity0Uqi5LwbkgfxqCCE5x5mXZIk9lTMeDz5vB9q6M5nzncVDy8F8przF3NbDLLgxKlt8wjiICg==", + "dev": true, "dependencies": { - "caniuse-lite": "^1.0.30001449", - "electron-to-chromium": "^1.4.284", - "node-releases": "^2.0.8", - "update-browserslist-db": "^1.0.10" + "@storybook/addon-actions": "7.6.10", + "@storybook/addon-backgrounds": "7.6.10", + "@storybook/addon-controls": "7.6.10", + "@storybook/addon-docs": "7.6.10", + "@storybook/addon-highlight": "7.6.10", + "@storybook/addon-measure": "7.6.10", + "@storybook/addon-outline": "7.6.10", + "@storybook/addon-toolbars": "7.6.10", + "@storybook/addon-viewport": "7.6.10", + "@storybook/core-common": "7.6.10", + "@storybook/manager-api": "7.6.10", + "@storybook/node-logger": "7.6.10", + "@storybook/preview-api": "7.6.10", + "ts-dedent": "^2.0.0" }, - "bin": { - "browserslist": "cli.js" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "node_modules/@storybook/addon-highlight": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/addon-highlight/-/addon-highlight-7.6.10.tgz", + "integrity": "sha512-dIuS5QmoT1R+gFOcf6CoBa6D9UR5/wHCfPqPRH8dNNcCLtIGSHWQ4v964mS5OCq1Huj7CghmR15lOUk7SaYwUA==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" + "@storybook/global": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" } }, - "node_modules/buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "node_modules/@storybook/addon-interactions": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/addon-interactions/-/addon-interactions-7.6.10.tgz", + "integrity": "sha512-lEsAdP/PrOZK/KmRbZ/fU4RjEqDP+e/PBlVVVJT2QvHniWK/xxkjCD0axsHU/XuaeQRFhmg0/KR342PC/cIf9A==", "dev": true, - "engines": { - "node": "*" + "dependencies": { + "@storybook/global": "^5.0.0", + "@storybook/types": "7.6.10", + "jest-mock": "^27.0.6", + "polished": "^4.2.2", + "ts-dedent": "^2.2.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" } }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" - }, - "node_modules/cache-content-type": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-content-type/-/cache-content-type-1.0.1.tgz", - "integrity": "sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA==", + "node_modules/@storybook/addon-links": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/addon-links/-/addon-links-7.6.10.tgz", + "integrity": "sha512-s/WkSYHpr2pb9p57j6u/xDBg3TKJhBq55YMl0GB5gXgkRPIeuGbPhGJhm2yTGVFLvXgr/aHHnOxb/R/W8PiRhA==", "dev": true, "dependencies": { - "mime-types": "^2.1.18", - "ylru": "^1.2.0" + "@storybook/csf": "^0.1.2", + "@storybook/global": "^5.0.0", + "ts-dedent": "^2.0.0" }, - "engines": { - "node": ">= 6.0.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + } } }, - "node_modules/cachedir": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.3.0.tgz", - "integrity": "sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw==", + "node_modules/@storybook/addon-measure": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/addon-measure/-/addon-measure-7.6.10.tgz", + "integrity": "sha512-OVfTI56+kc4hLWfZ/YPV3WKj/aA9e4iKXYxZyPdhfX4Z8TgZdD1wv9Z6e8DKS0H5kuybYrHKHaID5ki6t7qz3w==", "dev": true, - "engines": { - "node": ">=6" + "dependencies": { + "@storybook/global": "^5.0.0", + "tiny-invariant": "^1.3.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" } }, - "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "node_modules/@storybook/addon-outline": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/addon-outline/-/addon-outline-7.6.10.tgz", + "integrity": "sha512-RVJrEoPArhI6zAIMNl1Gz0zrj84BTfEWYYz0yDWOTVgvN411ugsoIk1hw0671MOneXJ2RcQ9MFIeV/v6AVDQYg==", + "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "@storybook/global": "^5.0.0", + "ts-dedent": "^2.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/storybook" } }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "engines": { - "node": ">=6" + "node_modules/@storybook/addon-toolbars": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/addon-toolbars/-/addon-toolbars-7.6.10.tgz", + "integrity": "sha512-PaXY/oj9yxF7/H0CNdQKcioincyCkfeHpISZriZbZqhyqsjn3vca7RFEmsB88Q+ou6rMeqyA9st+6e2cx/Ct6A==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" } }, - "node_modules/camelcase-css": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", - "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "node_modules/@storybook/addon-viewport": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/addon-viewport/-/addon-viewport-7.6.10.tgz", + "integrity": "sha512-+bA6juC/lH4vEhk+w0rXakaG8JgLG4MOYrIudk5vJKQaC6X58LIM9N4kzIS2KSExRhkExXBPrWsnMfCo7uxmKg==", "dev": true, - "engines": { - "node": ">= 6" + "dependencies": { + "memoizerific": "^1.11.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/blocks": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/blocks/-/blocks-7.6.10.tgz", + "integrity": "sha512-oSIukGC3yuF8pojABC/HLu5tv2axZvf60TaUs8eDg7+NiiKhzYSPoMQxs5uMrKngl+EJDB92ESgWT9vvsfvIPg==", + "dev": true, + "dependencies": { + "@storybook/channels": "7.6.10", + "@storybook/client-logger": "7.6.10", + "@storybook/components": "7.6.10", + "@storybook/core-events": "7.6.10", + "@storybook/csf": "^0.1.2", + "@storybook/docs-tools": "7.6.10", + "@storybook/global": "^5.0.0", + "@storybook/manager-api": "7.6.10", + "@storybook/preview-api": "7.6.10", + "@storybook/theming": "7.6.10", + "@storybook/types": "7.6.10", + "@types/lodash": "^4.14.167", + "color-convert": "^2.0.1", + "dequal": "^2.0.2", + "lodash": "^4.17.21", + "markdown-to-jsx": "^7.1.8", + "memoizerific": "^1.11.3", + "polished": "^4.2.2", + "react-colorful": "^5.1.2", + "telejson": "^7.2.0", + "tocbot": "^4.20.1", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, - "node_modules/caniuse-api": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", - "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", + "node_modules/@storybook/blocks/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "dependencies": { - "browserslist": "^4.0.0", - "caniuse-lite": "^1.0.0", - "lodash.memoize": "^4.1.2", - "lodash.uniq": "^4.5.0" + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "node_modules/caniuse-lite": { - "version": "1.0.30001503", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001503.tgz", - "integrity": "sha512-Sf9NiF+wZxPfzv8Z3iS0rXM1Do+iOy2Lxvib38glFX+08TCYYYGR5fRJXk4d77C4AYwhUjgYgMsMudbh2TqCKw==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ] + "node_modules/@storybook/blocks/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, - "node_modules/case-anything": { - "version": "2.1.11", - "resolved": "https://registry.npmjs.org/case-anything/-/case-anything-2.1.11.tgz", - "integrity": "sha512-uzKDXzdM/x914cepWPzElU3y50NRKYhjkO4ittOHLq+rF6M0AgRLF/+yPR1tvwLNAh8WHEPTfhuciZGPfX+oyg==", - "engines": { - "node": ">=12.13" + "node_modules/@storybook/builder-manager": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/builder-manager/-/builder-manager-7.6.10.tgz", + "integrity": "sha512-f+YrjZwohGzvfDtH8BHzqM3xW0p4vjjg9u7uzRorqUiNIAAKHpfNrZ/WvwPlPYmrpAHt4xX/nXRJae4rFSygPw==", + "dev": true, + "dependencies": { + "@fal-works/esbuild-plugin-global-externals": "^2.1.2", + "@storybook/core-common": "7.6.10", + "@storybook/manager": "7.6.10", + "@storybook/node-logger": "7.6.10", + "@types/ejs": "^3.1.1", + "@types/find-cache-dir": "^3.2.1", + "@yarnpkg/esbuild-plugin-pnp": "^3.0.0-rc.10", + "browser-assert": "^1.2.1", + "ejs": "^3.1.8", + "esbuild": "^0.18.0", + "esbuild-plugin-alias": "^0.2.1", + "express": "^4.17.3", + "find-cache-dir": "^3.0.0", + "fs-extra": "^11.1.0", + "process": "^0.11.10", + "util": "^0.12.4" }, "funding": { - "url": "https://github.com/sponsors/mesqueeb" + "type": "opencollective", + "url": "https://opencollective.com/storybook" } }, - "node_modules/caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", - "dev": true - }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "node_modules/@storybook/builder-manager/node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dev": true, "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, "engines": { - "node": ">=4" + "node": ">=14.14" } }, - "node_modules/chart.js": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.9.1.tgz", - "integrity": "sha512-Ro2JbLmvg83gXF5F4sniaQ+lTbSv18E+TIf2cOeiH1Iqd2PGFOtem+DUufMZsCJwFE7ywPOpfXFBwRTGq7dh6w==" - }, - "node_modules/chartjs-adapter-date-fns": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chartjs-adapter-date-fns/-/chartjs-adapter-date-fns-3.0.0.tgz", - "integrity": "sha512-Rs3iEB3Q5pJ973J93OBTpnP7qoGwvq3nUnoMdtxO+9aoJof7UFcRbWcIDteXuYd1fgAvct/32T9qaLyLuZVwCg==", - "optional": true, + "node_modules/@storybook/builder-vite": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/builder-vite/-/builder-vite-7.6.10.tgz", + "integrity": "sha512-qxe19axiNJVdIKj943e1ucAmADwU42fTGgMSdBzzrvfH3pSOmx2057aIxRzd8YtBRnj327eeqpgCHYIDTunMYQ==", + "dev": true, + "dependencies": { + "@storybook/channels": "7.6.10", + "@storybook/client-logger": "7.6.10", + "@storybook/core-common": "7.6.10", + "@storybook/csf-plugin": "7.6.10", + "@storybook/node-logger": "7.6.10", + "@storybook/preview": "7.6.10", + "@storybook/preview-api": "7.6.10", + "@storybook/types": "7.6.10", + "@types/find-cache-dir": "^3.2.1", + "browser-assert": "^1.2.1", + "es-module-lexer": "^0.9.3", + "express": "^4.17.3", + "find-cache-dir": "^3.0.0", + "fs-extra": "^11.1.0", + "magic-string": "^0.30.0", + "rollup": "^2.25.0 || ^3.3.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, "peerDependencies": { - "chart.js": ">=2.8.0", - "date-fns": ">=2.0.0" + "@preact/preset-vite": "*", + "typescript": ">= 4.3.x", + "vite": "^3.0.0 || ^4.0.0 || ^5.0.0", + "vite-plugin-glimmerx": "*" + }, + "peerDependenciesMeta": { + "@preact/preset-vite": { + "optional": true + }, + "typescript": { + "optional": true + }, + "vite-plugin-glimmerx": { + "optional": true + } } }, - "node_modules/chartjs-adapter-moment": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/chartjs-adapter-moment/-/chartjs-adapter-moment-1.0.1.tgz", - "integrity": "sha512-Uz+nTX/GxocuqXpGylxK19YG4R3OSVf8326D+HwSTsNw1LgzyIGRo+Qujwro1wy6X+soNSnfj5t2vZ+r6EaDmA==", - "peerDependencies": { - "chart.js": ">=3.0.0", - "moment": "^2.10.2" - } + "node_modules/@storybook/builder-vite/node_modules/es-module-lexer": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", + "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", + "dev": true }, - "node_modules/chartjs-plugin-annotation": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/chartjs-plugin-annotation/-/chartjs-plugin-annotation-2.2.1.tgz", - "integrity": "sha512-RL9UtrFr2SXd7C47zD0MZqn6ZLgrcRt3ySC6cYal2amBdANcYB1QcwFXcpKWAYnO4SGJYRok7P5rKDDNgJMA/w==", - "peerDependencies": { - "chart.js": ">=3.7.0" + "node_modules/@storybook/builder-vite/node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" } }, - "node_modules/chartkick": { - "version": "4.1.1", - "resolved": "git+ssh://git@github.com/CrowdDotDev/chartkick.js.git#622a0fa30efebe1ff7380e4182536cc2816c8da5", - "license": "MIT", - "optionalDependencies": { - "chart.js": ">=3.0.2", - "chartjs-adapter-date-fns": ">=2.0.0", - "date-fns": ">=2.0.0" + "node_modules/@storybook/channels": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-7.6.10.tgz", + "integrity": "sha512-ITCLhFuDBKgxetuKnWwYqMUWlU7zsfH3gEKZltTb+9/2OAWR7ez0iqU7H6bXP1ridm0DCKkt2UMWj2mmr9iQqg==", + "dev": true, + "dependencies": { + "@storybook/client-logger": "7.6.10", + "@storybook/core-events": "7.6.10", + "@storybook/global": "^5.0.0", + "qs": "^6.10.0", + "telejson": "^7.2.0", + "tiny-invariant": "^1.3.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/cli": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/cli/-/cli-7.6.10.tgz", + "integrity": "sha512-pK1MEseMm73OMO2OVoSz79QWX8ymxgIGM8IeZTCo9gImiVRChMNDFYcv8yPWkjuyesY8c15CoO48aR7pdA1OjQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.23.2", + "@babel/preset-env": "^7.23.2", + "@babel/types": "^7.23.0", + "@ndelangen/get-tarball": "^3.0.7", + "@storybook/codemod": "7.6.10", + "@storybook/core-common": "7.6.10", + "@storybook/core-events": "7.6.10", + "@storybook/core-server": "7.6.10", + "@storybook/csf-tools": "7.6.10", + "@storybook/node-logger": "7.6.10", + "@storybook/telemetry": "7.6.10", + "@storybook/types": "7.6.10", + "@types/semver": "^7.3.4", + "@yarnpkg/fslib": "2.10.3", + "@yarnpkg/libzip": "2.3.0", + "chalk": "^4.1.0", + "commander": "^6.2.1", + "cross-spawn": "^7.0.3", + "detect-indent": "^6.1.0", + "envinfo": "^7.7.3", + "execa": "^5.0.0", + "express": "^4.17.3", + "find-up": "^5.0.0", + "fs-extra": "^11.1.0", + "get-npm-tarball-url": "^2.0.3", + "get-port": "^5.1.1", + "giget": "^1.0.0", + "globby": "^11.0.2", + "jscodeshift": "^0.15.1", + "leven": "^3.1.0", + "ora": "^5.4.1", + "prettier": "^2.8.0", + "prompts": "^2.4.0", + "puppeteer-core": "^2.1.1", + "read-pkg-up": "^7.0.1", + "semver": "^7.3.7", + "strip-json-comments": "^3.0.1", + "tempy": "^1.0.1", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2" + }, + "bin": { + "getstorybook": "bin/index.js", + "sb": "bin/index.js" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" } }, - "node_modules/check-more-types": { - "version": "2.24.0", - "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", - "integrity": "sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==", + "node_modules/@storybook/cli/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">= 0.8.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "devOptional": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], + "node_modules/@storybook/cli/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">= 8.10.0" + "node": ">=10" }, - "optionalDependencies": { - "fsevents": "~2.3.2" + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "devOptional": true, + "node_modules/@storybook/cli/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { - "is-glob": "^4.0.1" + "color-name": "~1.1.4" }, "engines": { - "node": ">= 6" + "node": ">=7.0.0" } }, - "node_modules/chrome-trace-event": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", - "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", - "peer": true, + "node_modules/@storybook/cli/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@storybook/cli/node_modules/commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "dev": true, "engines": { - "node": ">=6.0" + "node": ">= 6" } }, - "node_modules/ci-info": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", - "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", + "node_modules/@storybook/cli/node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, "engines": { - "node": ">=8" + "node": ">=14.14" } }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "node_modules/@storybook/cli/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": ">=6" + "node": ">=8" } }, - "node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "node_modules/@storybook/cli/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "dependencies": { - "restore-cursor": "^3.1.0" + "yallist": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/cli-table3": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz", - "integrity": "sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==", + "node_modules/@storybook/cli/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "dependencies": { - "string-width": "^4.2.0" + "lru-cache": "^6.0.0" }, - "engines": { - "node": "10.* || >= 12.*" + "bin": { + "semver": "bin/semver.js" }, - "optionalDependencies": { - "@colors/colors": "1.5.0" + "engines": { + "node": ">=10" } }, - "node_modules/cli-truncate": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", - "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", + "node_modules/@storybook/cli/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "dependencies": { - "slice-ansi": "^3.0.0", - "string-width": "^4.2.0" + "has-flag": "^4.0.0" }, "engines": { "node": ">=8" + } + }, + "node_modules/@storybook/cli/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/@storybook/client-logger": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-7.6.10.tgz", + "integrity": "sha512-U7bbpu21ntgePMz/mKM18qvCSWCUGCUlYru8mgVlXLCKqFqfTeP887+CsPEQf29aoE3cLgDrxqbRJ1wxX9kL9A==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/codemod": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/codemod/-/codemod-7.6.10.tgz", + "integrity": "sha512-pzFR0nocBb94vN9QCJLC3C3dP734ZigqyPmd0ZCDj9Xce2ytfHK3v1lKB6TZWzKAZT8zztauECYxrbo4LVuagw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.23.2", + "@babel/preset-env": "^7.23.2", + "@babel/types": "^7.23.0", + "@storybook/csf": "^0.1.2", + "@storybook/csf-tools": "7.6.10", + "@storybook/node-logger": "7.6.10", + "@storybook/types": "7.6.10", + "@types/cross-spawn": "^6.0.2", + "cross-spawn": "^7.0.3", + "globby": "^11.0.2", + "jscodeshift": "^0.15.1", + "lodash": "^4.17.21", + "prettier": "^2.8.0", + "recast": "^0.23.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" } }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "node_modules/@storybook/components": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/components/-/components-7.6.10.tgz", + "integrity": "sha512-H5hF8pxwtbt0LxV24KMMsPlbYG9Oiui3ObvAQkvGu6q62EYxRPeNSrq3GBI5XEbI33OJY9bT24cVaZx18dXqwQ==", "dev": true, "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" + "@radix-ui/react-select": "^1.2.2", + "@radix-ui/react-toolbar": "^1.0.4", + "@storybook/client-logger": "7.6.10", + "@storybook/csf": "^0.1.2", + "@storybook/global": "^5.0.0", + "@storybook/theming": "7.6.10", + "@storybook/types": "7.6.10", + "memoizerific": "^1.11.3", + "use-resize-observer": "^9.1.0", + "util-deprecate": "^1.0.2" }, - "engines": { - "node": ">=12" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, - "node_modules/co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "node_modules/@storybook/core-client": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/core-client/-/core-client-7.6.10.tgz", + "integrity": "sha512-DjnzSzSNDmZyxyg6TxugzWQwOsW+n/iWVv6sHNEvEd5STr0mjuJjIEELmv58LIr5Lsre5+LEddqHsyuLyt8ubg==", "dev": true, - "engines": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" + "dependencies": { + "@storybook/client-logger": "7.6.10", + "@storybook/preview-api": "7.6.10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" } }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "node_modules/@storybook/core-common": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/core-common/-/core-common-7.6.10.tgz", + "integrity": "sha512-K3YWqjCKMnpvYsWNjOciwTH6zWbuuZzmOiipziZaVJ+sB1XYmH52Y3WGEm07TZI8AYK9DRgwA13dR/7W0nw72Q==", + "dev": true, "dependencies": { - "color-name": "1.1.3" + "@storybook/core-events": "7.6.10", + "@storybook/node-logger": "7.6.10", + "@storybook/types": "7.6.10", + "@types/find-cache-dir": "^3.2.1", + "@types/node": "^18.0.0", + "@types/node-fetch": "^2.6.4", + "@types/pretty-hrtime": "^1.0.0", + "chalk": "^4.1.0", + "esbuild": "^0.18.0", + "esbuild-register": "^3.5.0", + "file-system-cache": "2.3.0", + "find-cache-dir": "^3.0.0", + "find-up": "^5.0.0", + "fs-extra": "^11.1.0", + "glob": "^10.0.0", + "handlebars": "^4.7.7", + "lazy-universal-dotenv": "^4.0.0", + "node-fetch": "^2.0.0", + "picomatch": "^2.3.0", + "pkg-dir": "^5.0.0", + "pretty-hrtime": "^1.0.3", + "resolve-from": "^5.0.0", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" } }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "node_modules/colord": { - "version": "2.9.3", - "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", - "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", - "dev": true + "node_modules/@storybook/core-common/node_modules/@types/node": { + "version": "18.19.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.9.tgz", + "integrity": "sha512-oZFKlC8l5YtzGQNT4zC2PiSSKzQVZ8bAwwd+EYdPLtyk0nSEq6O16SkK+rkkT2eflDAbormJgEF3QnH3oDrTSw==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } }, - "node_modules/colorette": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz", - "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==", - "dev": true - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "node_modules/@storybook/core-common/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "delayed-stream": "~1.0.0" + "color-convert": "^2.0.1" }, "engines": { - "node": ">= 0.8" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/commander": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", - "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "node_modules/@storybook/core-common/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@storybook/core-common/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": ">= 6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/common-tags": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", - "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", + "node_modules/@storybook/core-common/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, "engines": { - "node": ">=4.0.0" + "node": ">=7.0.0" } }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + "node_modules/@storybook/core-common/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, - "node_modules/concurrently": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-7.6.0.tgz", - "integrity": "sha512-BKtRgvcJGeZ4XttiDiNcFiRlxoAeZOseqUvyYRUp/Vtd+9p1ULmeoSqGsDA+2ivdeDFpqrJvGvmI+StKfKl5hw==", + "node_modules/@storybook/core-common/node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", "dev": true, "dependencies": { - "chalk": "^4.1.0", - "date-fns": "^2.29.1", - "lodash": "^4.17.21", - "rxjs": "^7.0.0", - "shell-quote": "^1.7.3", - "spawn-command": "^0.0.2-1", - "supports-color": "^8.1.0", - "tree-kill": "^1.2.2", - "yargs": "^17.3.1" + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/@storybook/core-common/node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" }, "bin": { - "conc": "dist/bin/concurrently.js", - "concurrently": "dist/bin/concurrently.js" + "glob": "dist/esm/bin.mjs" }, "engines": { - "node": "^12.20.0 || ^14.13.0 || >=16.0.0" + "node": ">=16 || 14 >=14.17" }, "funding": { - "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/concurrently/node_modules/ansi-styles": { + "node_modules/@storybook/core-common/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/@storybook/core-common/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@storybook/core-common/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@storybook/core-common/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@storybook/core-events": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-7.6.10.tgz", + "integrity": "sha512-yccDH67KoROrdZbRKwxgTswFMAco5nlCyxszCDASCLygGSV2Q2e+YuywrhchQl3U6joiWi3Ps1qWu56NeNafag==", + "dev": true, + "dependencies": { + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/core-server": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/core-server/-/core-server-7.6.10.tgz", + "integrity": "sha512-2icnqJkn3vwq0eJPP0rNaHd7IOvxYf5q4lSVl2AWTxo/Ae19KhokI6j/2vvS2XQJMGQszwshlIwrZUNsj5p0yw==", + "dev": true, + "dependencies": { + "@aw-web-design/x-default-browser": "1.4.126", + "@discoveryjs/json-ext": "^0.5.3", + "@storybook/builder-manager": "7.6.10", + "@storybook/channels": "7.6.10", + "@storybook/core-common": "7.6.10", + "@storybook/core-events": "7.6.10", + "@storybook/csf": "^0.1.2", + "@storybook/csf-tools": "7.6.10", + "@storybook/docs-mdx": "^0.1.0", + "@storybook/global": "^5.0.0", + "@storybook/manager": "7.6.10", + "@storybook/node-logger": "7.6.10", + "@storybook/preview-api": "7.6.10", + "@storybook/telemetry": "7.6.10", + "@storybook/types": "7.6.10", + "@types/detect-port": "^1.3.0", + "@types/node": "^18.0.0", + "@types/pretty-hrtime": "^1.0.0", + "@types/semver": "^7.3.4", + "better-opn": "^3.0.2", + "chalk": "^4.1.0", + "cli-table3": "^0.6.1", + "compression": "^1.7.4", + "detect-port": "^1.3.0", + "express": "^4.17.3", + "fs-extra": "^11.1.0", + "globby": "^11.0.2", + "ip": "^2.0.0", + "lodash": "^4.17.21", + "open": "^8.4.0", + "pretty-hrtime": "^1.0.3", + "prompts": "^2.4.0", + "read-pkg-up": "^7.0.1", + "semver": "^7.3.7", + "telejson": "^7.2.0", + "tiny-invariant": "^1.3.1", + "ts-dedent": "^2.0.0", + "util": "^0.12.4", + "util-deprecate": "^1.0.2", + "watchpack": "^2.2.0", + "ws": "^8.2.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/core-server/node_modules/@types/node": { + "version": "18.19.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.9.tgz", + "integrity": "sha512-oZFKlC8l5YtzGQNT4zC2PiSSKzQVZ8bAwwd+EYdPLtyk0nSEq6O16SkK+rkkT2eflDAbormJgEF3QnH3oDrTSw==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@storybook/core-server/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", @@ -4160,7 +5306,7 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/concurrently/node_modules/chalk": { + "node_modules/@storybook/core-server/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", @@ -4176,19 +5322,7 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/concurrently/node_modules/chalk/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/concurrently/node_modules/color-convert": { + "node_modules/@storybook/core-server/node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", @@ -4200,13 +5334,27 @@ "node": ">=7.0.0" } }, - "node_modules/concurrently/node_modules/color-name": { + "node_modules/@storybook/core-server/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/concurrently/node_modules/has-flag": { + "node_modules/@storybook/core-server/node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/@storybook/core-server/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==", @@ -4215,459 +5363,472 @@ "node": ">=8" } }, - "node_modules/concurrently/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==", + "node_modules/@storybook/core-server/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "yallist": "^4.0.0" }, "engines": { "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/confusing-browser-globals": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", - "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==" - }, - "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "node_modules/@storybook/core-server/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "dependencies": { - "safe-buffer": "5.2.1" + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">= 0.6" + "node": ">=10" } }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "node_modules/@storybook/core-server/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { - "node": ">= 0.6" + "node": ">=8" } }, - "node_modules/convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" + "node_modules/@storybook/core-server/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, - "node_modules/cookies": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/cookies/-/cookies-0.8.0.tgz", - "integrity": "sha512-8aPsApQfebXnuI+537McwYsDtjVxGm8gTIzQI3FDW6t5t/DAhERxtnbEPN/8RX+uZthoz4eCOgloXaE5cYyNow==", + "node_modules/@storybook/csf": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@storybook/csf/-/csf-0.1.2.tgz", + "integrity": "sha512-ePrvE/pS1vsKR9Xr+o+YwdqNgHUyXvg+1Xjx0h9LrVx7Zq4zNe06pd63F5EvzTbCbJsHj7GHr9tkiaqm7U8WRA==", "dev": true, "dependencies": { - "depd": "~2.0.0", - "keygrip": "~1.1.0" - }, - "engines": { - "node": ">= 0.8" + "type-fest": "^2.19.0" } }, - "node_modules/cookies/node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "node_modules/@storybook/csf-plugin": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/csf-plugin/-/csf-plugin-7.6.10.tgz", + "integrity": "sha512-Sc+zZg/BnPH2X28tthNaQBnDiFfO0QmfjVoOx0fGYM9SvY3P5ehzWwp5hMRBim6a/twOTzePADtqYL+t6GMqqg==", "dev": true, - "engines": { - "node": ">= 0.8" + "dependencies": { + "@storybook/csf-tools": "7.6.10", + "unplugin": "^1.3.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" } }, - "node_modules/core-js": { - "version": "3.24.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.24.1.tgz", - "integrity": "sha512-0QTBSYSUZ6Gq21utGzkfITDylE8jWC9Ne1D2MrhvlsZBI1x39OdDIVbzSqtgMndIy6BlHxBXpMGqzZmnztg2rg==", - "hasInstallScript": true, + "node_modules/@storybook/csf-tools": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/csf-tools/-/csf-tools-7.6.10.tgz", + "integrity": "sha512-TnDNAwIALcN6SA4l00Cb67G02XMOrYU38bIpFJk5VMDX2dvgPjUtJNBuLmEbybGcOt7nPyyFIHzKcY5FCVGoWA==", + "dev": true, + "dependencies": { + "@babel/generator": "^7.23.0", + "@babel/parser": "^7.23.0", + "@babel/traverse": "^7.23.2", + "@babel/types": "^7.23.0", + "@storybook/csf": "^0.1.2", + "@storybook/types": "7.6.10", + "fs-extra": "^11.1.0", + "recast": "^0.23.1", + "ts-dedent": "^2.0.0" + }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/core-js" + "url": "https://opencollective.com/storybook" } }, - "node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", - "dev": true - }, - "node_modules/crelt": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.5.tgz", - "integrity": "sha512-+BO9wPPi+DWTDcNYhr/W90myha8ptzftZT+LwcmUbbok0rcP/fequmFYCw8NMoH7pkAZQzU78b3kYrlua5a9eA==" - }, - "node_modules/cross-fetch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", - "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", + "node_modules/@storybook/csf-tools/node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dev": true, "dependencies": { - "node-fetch": "2.6.7" + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" } }, - "node_modules/cross-fetch/node_modules/node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "dependencies": { - "whatwg-url": "^5.0.0" - }, + "node_modules/@storybook/csf/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true, "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" + "node": ">=12.20" }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "node_modules/@storybook/docs-mdx": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@storybook/docs-mdx/-/docs-mdx-0.1.0.tgz", + "integrity": "sha512-JDaBR9lwVY4eSH5W8EGHrhODjygPd6QImRbwjAuJNEnY0Vw4ie3bPkeGfnacB3OBW6u/agqPv2aRlR46JcAQLg==", + "dev": true + }, + "node_modules/@storybook/docs-tools": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/docs-tools/-/docs-tools-7.6.10.tgz", + "integrity": "sha512-UgbikducoXzqQHf2TozO0f2rshaeBNnShVbL5Ai4oW7pDymBmrfzdjGbF/milO7yxNKcoIByeoNmu384eBamgQ==", + "dev": true, "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "@storybook/core-common": "7.6.10", + "@storybook/preview-api": "7.6.10", + "@storybook/types": "7.6.10", + "@types/doctrine": "^0.0.3", + "assert": "^2.1.0", + "doctrine": "^3.0.0", + "lodash": "^4.17.21" }, - "engines": { - "node": ">= 8" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" } }, - "node_modules/css-declaration-sorter": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.4.0.tgz", - "integrity": "sha512-jDfsatwWMWN0MODAFuHszfjphEXfNw9JUAhmY4pLu3TyTU+ohUpsbVtbU+1MZn4a47D9kqh03i4eyOm+74+zew==", + "node_modules/@storybook/global": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@storybook/global/-/global-5.0.0.tgz", + "integrity": "sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ==", + "dev": true + }, + "node_modules/@storybook/instrumenter": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/instrumenter/-/instrumenter-7.6.10.tgz", + "integrity": "sha512-9FYXW1CKXnZ7yYmy2A6U0seqJMe1F7g55J28Vslk3ZLoGATFJ2BR0eoQS+cgfBly6djehjaVeuV3IcUYGnQ/6Q==", "dev": true, - "engines": { - "node": "^10 || ^12 || >=14" + "dependencies": { + "@storybook/channels": "7.6.10", + "@storybook/client-logger": "7.6.10", + "@storybook/core-events": "7.6.10", + "@storybook/global": "^5.0.0", + "@storybook/preview-api": "7.6.10", + "@vitest/utils": "^0.34.6", + "util": "^0.12.4" }, - "peerDependencies": { - "postcss": "^8.0.9" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" } }, - "node_modules/css-minimizer-webpack-plugin": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-4.2.2.tgz", - "integrity": "sha512-s3Of/4jKfw1Hj9CxEO1E5oXhQAxlayuHO2y/ML+C6I9sQ7FdzfEV6QgMLN3vI+qFsjJGIAFLKtQK7t8BOXAIyA==", + "node_modules/@storybook/manager": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/manager/-/manager-7.6.10.tgz", + "integrity": "sha512-Co3sLCbNYY6O4iH2ggmRDLCPWLj03JE5s/DOG8OVoXc6vBwTc/Qgiyrsxxp6BHQnPpM0mxL6aKAxE3UjsW/Nog==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/manager-api": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/manager-api/-/manager-api-7.6.10.tgz", + "integrity": "sha512-8eGVpRlpunuFScDtc7nxpPJf/4kJBAAZlNdlhmX09j8M3voX6GpcxabBamSEX5pXZqhwxQCshD4IbqBmjvadlw==", "dev": true, "dependencies": { - "cssnano": "^5.1.8", - "jest-worker": "^29.1.2", - "postcss": "^8.4.17", - "schema-utils": "^4.0.0", - "serialize-javascript": "^6.0.0", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">= 14.15.0" + "@storybook/channels": "7.6.10", + "@storybook/client-logger": "7.6.10", + "@storybook/core-events": "7.6.10", + "@storybook/csf": "^0.1.2", + "@storybook/global": "^5.0.0", + "@storybook/router": "7.6.10", + "@storybook/theming": "7.6.10", + "@storybook/types": "7.6.10", + "dequal": "^2.0.2", + "lodash": "^4.17.21", + "memoizerific": "^1.11.3", + "store2": "^2.14.2", + "telejson": "^7.2.0", + "ts-dedent": "^2.0.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "@parcel/css": { - "optional": true - }, - "@swc/css": { - "optional": true - }, - "clean-css": { - "optional": true - }, - "csso": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "lightningcss": { - "optional": true - } + "url": "https://opencollective.com/storybook" } }, - "node_modules/css-minimizer-webpack-plugin/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "node_modules/@storybook/mdx2-csf": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@storybook/mdx2-csf/-/mdx2-csf-1.1.0.tgz", + "integrity": "sha512-TXJJd5RAKakWx4BtpwvSNdgTDkKM6RkXU8GK34S/LhidQ5Pjz3wcnqb0TxEkfhK/ztbP8nKHqXFwLfa2CYkvQw==", + "dev": true + }, + "node_modules/@storybook/node-logger": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-7.6.10.tgz", + "integrity": "sha512-ZBuqrv4bjJzKXyfRGFkVIi+z6ekn6rOPoQao4KmsfLNQAUUsEdR8Baw/zMnnU417zw5dSEaZdpuwx75SCQAeOA==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/postinstall": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/postinstall/-/postinstall-7.6.10.tgz", + "integrity": "sha512-SMdXtednPCy3+SRJ7oN1OPN1oVFhj3ih+ChOEX8/kZ5J3nfmV3wLPtsZvFGUCf0KWQEP1xL+1Urv48mzMKcV/w==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/preview": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/preview/-/preview-7.6.10.tgz", + "integrity": "sha512-F07BzVXTD3byq+KTWtvsw3pUu3fQbyiBNLFr2CnfU4XSdLKja5lDt8VqDQq70TayVQOf5qfUTzRd4M6pQkjw1w==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/preview-api": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-7.6.10.tgz", + "integrity": "sha512-5A3etoIwZCx05yuv3KSTv1wynN4SR4rrzaIs/CTBp3BC4q1RBL+Or/tClk0IJPXQMlx/4Y134GtNIBbkiDofpw==", "dev": true, "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "@storybook/channels": "7.6.10", + "@storybook/client-logger": "7.6.10", + "@storybook/core-events": "7.6.10", + "@storybook/csf": "^0.1.2", + "@storybook/global": "^5.0.0", + "@storybook/types": "7.6.10", + "@types/qs": "^6.9.5", + "dequal": "^2.0.2", + "lodash": "^4.17.21", + "memoizerific": "^1.11.3", + "qs": "^6.10.0", + "synchronous-promise": "^2.0.15", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "type": "opencollective", + "url": "https://opencollective.com/storybook" } }, - "node_modules/css-minimizer-webpack-plugin/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "node_modules/@storybook/react-dom-shim": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-7.6.10.tgz", + "integrity": "sha512-M+N/h6ximacaFdIDjMN2waNoWwApeVYTpFeoDppiFTvdBTXChyIuiPgYX9QSg7gDz92OaA52myGOot4wGvXVzg==", "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" }, "peerDependencies": { - "ajv": "^8.8.2" + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, - "node_modules/css-minimizer-webpack-plugin/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "node_modules/css-minimizer-webpack-plugin/node_modules/schema-utils": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", - "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", + "node_modules/@storybook/router": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/router/-/router-7.6.10.tgz", + "integrity": "sha512-G/H4Jn2+y8PDe8Zbq4DVxF/TPn0/goSItdILts39JENucHiuGBCjKjSWGBe1rkwKi1tUbB3yhxJVrLagxFEPpQ==", "dev": true, "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.8.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.0.0" - }, - "engines": { - "node": ">= 12.13.0" + "@storybook/client-logger": "7.6.10", + "memoizerific": "^1.11.3", + "qs": "^6.10.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/webpack" + "url": "https://opencollective.com/storybook" } }, - "node_modules/css-select": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", - "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "node_modules/@storybook/telemetry": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/telemetry/-/telemetry-7.6.10.tgz", + "integrity": "sha512-p3mOSUtIyy2tF1z6pQXxNh1JzYFcAm97nUgkwLzF07GfEdVAPM+ftRSLFbD93zVvLEkmLTlsTiiKaDvOY/lQWg==", "dev": true, "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.0.1", - "domhandler": "^4.3.1", - "domutils": "^2.8.0", - "nth-check": "^2.0.1" + "@storybook/client-logger": "7.6.10", + "@storybook/core-common": "7.6.10", + "@storybook/csf-tools": "7.6.10", + "chalk": "^4.1.0", + "detect-package-manager": "^2.0.1", + "fetch-retry": "^5.0.2", + "fs-extra": "^11.1.0", + "read-pkg-up": "^7.0.1" }, "funding": { - "url": "https://github.com/sponsors/fb55" + "type": "opencollective", + "url": "https://opencollective.com/storybook" } }, - "node_modules/css-tree": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", - "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "node_modules/@storybook/telemetry/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "mdn-data": "2.0.14", - "source-map": "^0.6.1" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=8.0.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "node_modules/@storybook/telemetry/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": ">= 6" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/fb55" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "bin": { - "cssesc": "bin/cssesc" + "node_modules/@storybook/telemetry/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" }, "engines": { - "node": ">=4" + "node": ">=7.0.0" } }, - "node_modules/cssnano": { - "version": "5.1.15", - "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.15.tgz", - "integrity": "sha512-j+BKgDcLDQA+eDifLx0EO4XSA56b7uut3BQFH+wbSaSTuGLuiyTa/wbRYthUXX8LC9mLg+WWKe8h+qJuwTAbHw==", + "node_modules/@storybook/telemetry/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@storybook/telemetry/node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", "dev": true, "dependencies": { - "cssnano-preset-default": "^5.2.14", - "lilconfig": "^2.0.3", - "yaml": "^1.10.2" + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/cssnano" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node": ">=14.14" } }, - "node_modules/cssnano-preset-default": { - "version": "5.2.14", - "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.2.14.tgz", - "integrity": "sha512-t0SFesj/ZV2OTylqQVOrFgEh5uanxbO6ZAdeCrNsUQ6fVuXwYTxJPNAGvGTxHbD68ldIJNec7PyYZDBrfDQ+6A==", - "dev": true, - "dependencies": { - "css-declaration-sorter": "^6.3.1", - "cssnano-utils": "^3.1.0", - "postcss-calc": "^8.2.3", - "postcss-colormin": "^5.3.1", - "postcss-convert-values": "^5.1.3", - "postcss-discard-comments": "^5.1.2", - "postcss-discard-duplicates": "^5.1.0", - "postcss-discard-empty": "^5.1.1", - "postcss-discard-overridden": "^5.1.0", - "postcss-merge-longhand": "^5.1.7", - "postcss-merge-rules": "^5.1.4", - "postcss-minify-font-values": "^5.1.0", - "postcss-minify-gradients": "^5.1.1", - "postcss-minify-params": "^5.1.4", - "postcss-minify-selectors": "^5.2.1", - "postcss-normalize-charset": "^5.1.0", - "postcss-normalize-display-values": "^5.1.0", - "postcss-normalize-positions": "^5.1.1", - "postcss-normalize-repeat-style": "^5.1.1", - "postcss-normalize-string": "^5.1.0", - "postcss-normalize-timing-functions": "^5.1.0", - "postcss-normalize-unicode": "^5.1.1", - "postcss-normalize-url": "^5.1.0", - "postcss-normalize-whitespace": "^5.1.1", - "postcss-ordered-values": "^5.1.3", - "postcss-reduce-initial": "^5.1.2", - "postcss-reduce-transforms": "^5.1.0", - "postcss-svgo": "^5.1.0", - "postcss-unique-selectors": "^5.1.1" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/cssnano-utils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.1.0.tgz", - "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==", + "node_modules/@storybook/telemetry/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": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node": ">=8" } }, - "node_modules/csso": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", - "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", + "node_modules/@storybook/telemetry/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "dependencies": { - "css-tree": "^1.1.2" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=8.0.0" + "node": ">=8" } }, - "node_modules/csstype": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", - "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" - }, - "node_modules/cypress": { - "version": "10.11.0", - "resolved": "https://registry.npmjs.org/cypress/-/cypress-10.11.0.tgz", - "integrity": "sha512-lsaE7dprw5DoXM00skni6W5ElVVLGAdRUUdZjX2dYsGjbY/QnpzWZ95Zom1mkGg0hAaO/QVTZoFVS7Jgr/GUPA==", + "node_modules/@storybook/test": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/test/-/test-7.6.10.tgz", + "integrity": "sha512-dn/T+HcWOBlVh3c74BHurp++BaqBoQgNbSIaXlYDpJoZ+DzNIoEQVsWFYm5gCbtKK27iFd4n52RiQI3f6Vblqw==", "dev": true, - "hasInstallScript": true, "dependencies": { - "@cypress/request": "^2.88.10", - "@cypress/xvfb": "^1.2.4", - "@types/node": "^14.14.31", - "@types/sinonjs__fake-timers": "8.1.1", - "@types/sizzle": "^2.3.2", - "arch": "^2.2.0", - "blob-util": "^2.0.2", - "bluebird": "^3.7.2", - "buffer": "^5.6.0", - "cachedir": "^2.3.0", - "chalk": "^4.1.0", - "check-more-types": "^2.24.0", - "cli-cursor": "^3.1.0", - "cli-table3": "~0.6.1", - "commander": "^5.1.0", - "common-tags": "^1.8.0", - "dayjs": "^1.10.4", - "debug": "^4.3.2", - "enquirer": "^2.3.6", - "eventemitter2": "6.4.7", - "execa": "4.1.0", - "executable": "^4.1.1", - "extract-zip": "2.0.1", - "figures": "^3.2.0", - "fs-extra": "^9.1.0", - "getos": "^3.2.1", - "is-ci": "^3.0.0", - "is-installed-globally": "~0.4.0", - "lazy-ass": "^1.6.0", - "listr2": "^3.8.3", - "lodash": "^4.17.21", - "log-symbols": "^4.0.0", - "minimist": "^1.2.6", - "ospath": "^1.2.2", - "pretty-bytes": "^5.6.0", - "proxy-from-env": "1.0.0", - "request-progress": "^3.0.0", - "semver": "^7.3.2", - "supports-color": "^8.1.1", - "tmp": "~0.2.1", - "untildify": "^4.0.0", - "yauzl": "^2.10.0" - }, - "bin": { - "cypress": "bin/cypress" + "@storybook/client-logger": "7.6.10", + "@storybook/core-events": "7.6.10", + "@storybook/instrumenter": "7.6.10", + "@storybook/preview-api": "7.6.10", + "@testing-library/dom": "^9.3.1", + "@testing-library/jest-dom": "^6.1.3", + "@testing-library/user-event": "14.3.0", + "@types/chai": "^4", + "@vitest/expect": "^0.34.2", + "@vitest/spy": "^0.34.1", + "chai": "^4.3.7", + "util": "^0.12.4" }, - "engines": { - "node": ">=12.0.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" } }, - "node_modules/cypress-mailosaur": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/cypress-mailosaur/-/cypress-mailosaur-2.13.0.tgz", - "integrity": "sha512-xdv2994VkGH79Ag+OY2V1Tkr9Uy9p5wE+3u+SB6nnJEvEDIT5cVPsxVJxr91THwR34NWoS3zQBt5ai5ZVZ/1/w==", + "node_modules/@storybook/test/node_modules/@testing-library/jest-dom": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.3.0.tgz", + "integrity": "sha512-hJVIrkFizEQxoWsGBlycTcQhrpoCH4DhXfrnHFFXgkx3Xdm15zycsq5Ep+vpw4W8S0NJa8cxDHcuJib+1tEbhg==", "dev": true, + "dependencies": { + "@adobe/css-tools": "^4.3.2", + "@babel/runtime": "^7.9.2", + "aria-query": "^5.0.0", + "chalk": "^3.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.6.3", + "lodash": "^4.17.15", + "redent": "^3.0.0" + }, "engines": { - "node": ">= v10.0.0" + "node": ">=14", + "npm": ">=6", + "yarn": ">=1" }, "peerDependencies": { - "cypress": ">= 2.1.0" + "@jest/globals": ">= 28", + "@types/bun": "latest", + "@types/jest": ">= 28", + "jest": ">= 28", + "vitest": ">= 0.32" + }, + "peerDependenciesMeta": { + "@jest/globals": { + "optional": true + }, + "@types/bun": { + "optional": true + }, + "@types/jest": { + "optional": true + }, + "jest": { + "optional": true + }, + "vitest": { + "optional": true + } } }, - "node_modules/cypress/node_modules/ansi-styles": { + "node_modules/@storybook/test/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", @@ -4682,35 +5843,20 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/cypress/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/@storybook/test/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/cypress/node_modules/chalk/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, "engines": { "node": ">=8" } }, - "node_modules/cypress/node_modules/color-convert": { + "node_modules/@storybook/test/node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", @@ -4722,51 +5868,19 @@ "node": ">=7.0.0" } }, - "node_modules/cypress/node_modules/color-name": { + "node_modules/@storybook/test/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/cypress/node_modules/execa": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", - "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.0", - "get-stream": "^5.0.0", - "human-signals": "^1.1.1", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.0", - "onetime": "^5.1.0", - "signal-exit": "^3.0.2", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/cypress/node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "node_modules/@storybook/test/node_modules/dom-accessibility-api": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", + "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", + "dev": true }, - "node_modules/cypress/node_modules/has-flag": { + "node_modules/@storybook/test/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==", @@ -4775,1035 +5889,1252 @@ "node": ">=8" } }, - "node_modules/cypress/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "node_modules/@storybook/test/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cypress/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/@storybook/theming": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-7.6.10.tgz", + "integrity": "sha512-f5tuy7yV3TOP3fIboSqpgLHy0wKayAw/M8HxX0jVET4Z4fWlFK0BiHJabQ+XEdAfQM97XhPFHB2IPbwsqhCEcQ==", "dev": true, "dependencies": { - "yallist": "^4.0.0" + "@emotion/use-insertion-effect-with-fallbacks": "^1.0.0", + "@storybook/client-logger": "7.6.10", + "@storybook/global": "^5.0.0", + "memoizerific": "^1.11.3" }, - "engines": { - "node": ">=10" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, - "node_modules/cypress/node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "node_modules/@storybook/types": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/types/-/types-7.6.10.tgz", + "integrity": "sha512-hcS2HloJblaMpCAj2axgGV+53kgSRYPT0a1PG1IHsZaYQILfHSMmBqM8XzXXYTsgf9250kz3dqFX1l0n3EqMlQ==", "dev": true, "dependencies": { - "path-key": "^3.0.0" + "@storybook/channels": "7.6.10", + "@types/babel__core": "^7.0.0", + "@types/express": "^4.7.0", + "file-system-cache": "2.3.0" }, - "engines": { - "node": ">=8" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" } }, - "node_modules/cypress/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "node_modules/@storybook/vue3": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/vue3/-/vue3-7.6.10.tgz", + "integrity": "sha512-FeZ9zjuudQgCdKPs2K8sU6TgEyrMjKrCN3e8+XXX5CAMSwLDV8IfexaaMF0ehYW6Wp0dgCIm0cVNBV3u8vtRRw==", "dev": true, "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" + "@storybook/core-client": "7.6.10", + "@storybook/docs-tools": "7.6.10", + "@storybook/global": "^5.0.0", + "@storybook/preview-api": "7.6.10", + "@storybook/types": "7.6.10", + "@vue/compiler-core": "^3.0.0", + "lodash": "^4.17.21", + "ts-dedent": "^2.0.0", + "type-fest": "~2.19", + "vue-component-type-helpers": "latest" }, "engines": { - "node": ">=10" + "node": ">=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "vue": "^3.0.0" } }, - "node_modules/cypress/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==", + "node_modules/@storybook/vue3-vite": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/vue3-vite/-/vue3-vite-7.6.10.tgz", + "integrity": "sha512-5f0Rh4PTVEeAI86ybihfN+rHGXXLNiRsoGKinpJSb7hkfsq/L7u3sVCXJwH/qsG+rUJlZyHs3kfa4/Kgyyi3Mg==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "@storybook/builder-vite": "7.6.10", + "@storybook/core-server": "7.6.10", + "@storybook/vue3": "7.6.10", + "@vitejs/plugin-vue": "^4.0.0", + "magic-string": "^0.30.0", + "vue-docgen-api": "^4.40.0" }, "engines": { - "node": ">=10" + "node": "^14.18 || >=16" }, "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "vite": "^3.0.0 || ^4.0.0 || ^5.0.0" } }, - "node_modules/cypress/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/d3-dispatch": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", - "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", - "peer": true, + "node_modules/@storybook/vue3/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true, "engines": { - "node": ">=12" - } - }, - "node_modules/d3-force": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", - "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", - "peer": true, - "dependencies": { - "d3-dispatch": "1 - 3", - "d3-quadtree": "1 - 3", - "d3-timer": "1 - 3" + "node": ">=12.20" }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-quadtree": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", - "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", - "peer": true, - "engines": { - "node": ">=12" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/d3-timer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", - "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", - "peer": true, - "engines": { - "node": ">=12" + "node_modules/@tailwindcss/line-clamp": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/line-clamp/-/line-clamp-0.4.2.tgz", + "integrity": "sha512-HFzAQuqYCjyy/SX9sLGB1lroPzmcnWv1FHkIpmypte10hptf4oPUfucryMKovZh2u0uiS9U5Ty3GghWfEJGwVw==", + "dev": true, + "peerDependencies": { + "tailwindcss": ">=2.0.0 || >=3.0.0 || >=3.0.0-alpha.1" } }, - "node_modules/damerau-levenshtein": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", - "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==" - }, - "node_modules/dash-get": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/dash-get/-/dash-get-1.0.2.tgz", - "integrity": "sha512-4FbVrHDwfOASx7uQVxeiCTo7ggSdYZbqs8lH+WU6ViypPlDbe9y6IP5VVUDQBv9DcnyaiPT5XT0UWHgJ64zLeQ==" - }, - "node_modules/dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "node_modules/@testing-library/dom": { + "version": "9.3.4", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.3.4.tgz", + "integrity": "sha512-FlS4ZWlp97iiNWig0Muq8p+3rVDjRiYE+YKGbAqXOu9nwJFFOdL00kFpz42M+4huzYi86vAK1sOOfyOG45muIQ==", "dev": true, "dependencies": { - "assert-plus": "^1.0.0" + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.1.3", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" }, "engines": { - "node": ">=0.10" + "node": ">=14" } }, - "node_modules/date-fns": { - "version": "2.29.3", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz", - "integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==", - "devOptional": true, + "node_modules/@testing-library/dom/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">=0.11" + "node": ">=8" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/date-fns" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/dayjs": { - "version": "1.11.7", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.7.tgz", - "integrity": "sha512-+Yw9U6YO5TQohxLcIkrXBeY73WP3ejHWVvx8XCk3gxvQDCTEmS48ZrSZCKciI7Bhl/uCMyxYtE9UqRILmFphkQ==" - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "node_modules/@testing-library/dom/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { - "ms": "2.1.2" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=6.0" + "node": ">=10" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/deep-equal": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.0.tgz", - "integrity": "sha512-RdpzE0Hv4lhowpIUKKMJfeH6C1pXdtT1/it80ubgWqwI3qpuxUBpC1S4hnHg+zjnuOoDkzUtUCEEkG+XG5l3Mw==", + "node_modules/@testing-library/dom/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "es-get-iterator": "^1.1.2", - "get-intrinsic": "^1.1.3", - "is-arguments": "^1.1.1", - "is-array-buffer": "^3.0.1", - "is-date-object": "^1.0.5", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "isarray": "^2.0.5", - "object-is": "^1.1.5", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", - "side-channel": "^1.0.4", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" + "color-name": "~1.1.4" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=7.0.0" } }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" + "node_modules/@testing-library/dom/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, - "node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "node_modules/@testing-library/dom/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": ">=0.10.0" + "node": ">=8" } }, - "node_modules/define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "node_modules/@testing-library/dom/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { "node": ">=8" } }, - "node_modules/define-properties": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", - "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", - "dependencies": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, + "node_modules/@testing-library/user-event": { + "version": "14.3.0", + "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.3.0.tgz", + "integrity": "sha512-P02xtBBa8yMaLhK8CzJCIns8rqwnF6FxhR9zs810flHOBXUYCFjLd8Io1rQrAkQRWEmW2PGdZIEdMxf/KLsqFA==", + "dev": true, "engines": { - "node": ">= 0.4" + "node": ">=12", + "npm": ">=6" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "@testing-library/dom": ">=7.21.4" } }, - "node_modules/defined": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.1.tgz", - "integrity": "sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q==", - "dev": true, + "node_modules/@tiptap/core": { + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/@tiptap/core/-/core-2.1.12.tgz", + "integrity": "sha512-ZGc3xrBJA9KY8kln5AYTj8y+GDrKxi7u95xIl2eccrqTY5CQeRu6HRNM1yT4mAjuSaG9jmazyjGRlQuhyxCKxQ==", "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/pm": "^2.0.0" } }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, - "engines": { - "node": ">=0.4.0" + "node_modules/@tiptap/extension-blockquote": { + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/@tiptap/extension-blockquote/-/extension-blockquote-2.1.12.tgz", + "integrity": "sha512-Qb3YRlCfugx9pw7VgLTb+jY37OY4aBJeZnqHzx4QThSm13edNYjasokbX0nTwL1Up4NPTcY19JUeHt6fVaVVGg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.0.0" } }, - "node_modules/delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", - "dev": true + "node_modules/@tiptap/extension-bold": { + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/@tiptap/extension-bold/-/extension-bold-2.1.12.tgz", + "integrity": "sha512-AZGxIxcGU1/y6V2YEbKsq6BAibL8yQrbRm6EdcBnby41vj1WziewEKswhLGmZx5IKM2r2ldxld03KlfSIlKQZg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.0.0" + } }, - "node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", - "dev": true, - "engines": { - "node": ">= 0.6" + "node_modules/@tiptap/extension-bubble-menu": { + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/@tiptap/extension-bubble-menu/-/extension-bubble-menu-2.1.12.tgz", + "integrity": "sha512-gAGi21EQ4wvLmT7klgariAc2Hf+cIjaNU2NWze3ut6Ku9gUo5ZLqj1t9SKHmNf4d5JG63O8GxpErqpA7lHlRtw==", + "dependencies": { + "tippy.js": "^6.3.7" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.0.0", + "@tiptap/pm": "^2.0.0" } }, - "node_modules/deprecation": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", - "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" - }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "dev": true, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" + "node_modules/@tiptap/extension-bullet-list": { + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/@tiptap/extension-bullet-list/-/extension-bullet-list-2.1.12.tgz", + "integrity": "sha512-vtD8vWtNlmAZX8LYqt2yU9w3mU9rPCiHmbp4hDXJs2kBnI0Ju/qAyXFx6iJ3C3XyuMnMbJdDI9ee0spAvFz7cQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.0.0" } }, - "node_modules/detective": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.1.tgz", - "integrity": "sha512-v9XE1zRnz1wRtgurGu0Bs8uHKFSTdteYZNbIPFVhUZ39L/S79ppMpdmVOZAnoz1jfEFodc48n6MX483Xo3t1yw==", - "dev": true, - "dependencies": { - "acorn-node": "^1.8.2", - "defined": "^1.0.0", - "minimist": "^1.2.6" - }, - "bin": { - "detective": "bin/detective.js" + "node_modules/@tiptap/extension-code": { + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/@tiptap/extension-code/-/extension-code-2.1.12.tgz", + "integrity": "sha512-CRiRq5OTC1lFgSx6IMrECqmtb93a0ZZKujEnaRhzWliPBjLIi66va05f/P1vnV6/tHaC3yfXys6dxB5A4J8jxw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" }, - "engines": { - "node": ">=0.8.0" + "peerDependencies": { + "@tiptap/core": "^2.0.0" } }, - "node_modules/didyoumean": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", - "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", - "dev": true - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" + "node_modules/@tiptap/extension-code-block": { + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/@tiptap/extension-code-block/-/extension-code-block-2.1.12.tgz", + "integrity": "sha512-RXtSYCVsnk8D+K80uNZShClfZjvv1EgO42JlXLVGWQdIgaNyuOv/6I/Jdf+ZzhnpsBnHufW+6TJjwP5vJPSPHA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" }, - "engines": { - "node": ">=8" + "peerDependencies": { + "@tiptap/core": "^2.0.0", + "@tiptap/pm": "^2.0.0" } }, - "node_modules/dlv": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", - "dev": true + "node_modules/@tiptap/extension-document": { + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/@tiptap/extension-document/-/extension-document-2.1.12.tgz", + "integrity": "sha512-0QNfAkCcFlB9O8cUNSwTSIQMV9TmoEhfEaLz/GvbjwEq4skXK3bU+OQX7Ih07waCDVXIGAZ7YAZogbvrn/WbOw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.0.0" + } }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dependencies": { - "esutils": "^2.0.2" + "node_modules/@tiptap/extension-dropcursor": { + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/@tiptap/extension-dropcursor/-/extension-dropcursor-2.1.12.tgz", + "integrity": "sha512-0tT/q8nL4NBCYPxr9T0Brck+RQbWuczm9nV0bnxgt0IiQXoRHutfPWdS7GA65PTuVRBS/3LOco30fbjFhkfz/A==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" }, - "engines": { - "node": ">=6.0.0" + "peerDependencies": { + "@tiptap/core": "^2.0.0", + "@tiptap/pm": "^2.0.0" } }, - "node_modules/dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", - "dev": true, + "node_modules/@tiptap/extension-floating-menu": { + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/@tiptap/extension-floating-menu/-/extension-floating-menu-2.1.12.tgz", + "integrity": "sha512-uo0ydCJNg6AWwLT6cMUJYVChfvw2PY9ZfvKRhh9YJlGfM02jS4RUG/bJBts6R37f+a5FsOvAVwg8EvqPlNND1A==", "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" + "tippy.js": "^6.3.7" }, "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.0.0", + "@tiptap/pm": "^2.0.0" } }, - "node_modules/dom-serializer/node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "dev": true, + "node_modules/@tiptap/extension-gapcursor": { + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/@tiptap/extension-gapcursor/-/extension-gapcursor-2.1.12.tgz", + "integrity": "sha512-zFYdZCqPgpwoB7whyuwpc8EYLYjUE5QYKb8vICvc+FraBUDM51ujYhFSgJC3rhs8EjI+8GcK8ShLbSMIn49YOQ==", "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.0.0", + "@tiptap/pm": "^2.0.0" } }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ] - }, - "node_modules/domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "dev": true, - "dependencies": { - "domelementtype": "^2.2.0" - }, - "engines": { - "node": ">= 4" + "node_modules/@tiptap/extension-hard-break": { + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/@tiptap/extension-hard-break/-/extension-hard-break-2.1.12.tgz", + "integrity": "sha512-nqKcAYGEOafg9D+2cy1E4gHNGuL12LerVa0eS2SQOb+PT8vSel9OTKU1RyZldsWSQJ5rq/w4uIjmLnrSR2w6Yw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" }, + "peerDependencies": { + "@tiptap/core": "^2.0.0" + } + }, + "node_modules/@tiptap/extension-heading": { + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/@tiptap/extension-heading/-/extension-heading-2.1.12.tgz", + "integrity": "sha512-MoANP3POAP68Ko9YXarfDKLM/kXtscgp6m+xRagPAghRNujVY88nK1qBMZ3JdvTVN6b/ATJhp8UdrZX96TLV2w==", "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.0.0" } }, - "node_modules/domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "dev": true, - "dependencies": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" + "node_modules/@tiptap/extension-history": { + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/@tiptap/extension-history/-/extension-history-2.1.12.tgz", + "integrity": "sha512-6b7UFVkvPjq3LVoCTrYZAczt5sQrQUaoDWAieVClVZoFLfjga2Fwjcfgcie8IjdPt8YO2hG/sar/c07i9vM0Sg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" }, + "peerDependencies": { + "@tiptap/core": "^2.0.0", + "@tiptap/pm": "^2.0.0" + } + }, + "node_modules/@tiptap/extension-horizontal-rule": { + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-2.1.12.tgz", + "integrity": "sha512-RRuoK4KxrXRrZNAjJW5rpaxjiP0FJIaqpi7nFbAua2oHXgsCsG8qbW2Y0WkbIoS8AJsvLZ3fNGsQ8gpdliuq3A==", "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.0.0", + "@tiptap/pm": "^2.0.0" } }, - "node_modules/dotenv": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", - "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==", - "dev": true, - "engines": { - "node": ">=12" + "node_modules/@tiptap/extension-italic": { + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/@tiptap/extension-italic/-/extension-italic-2.1.12.tgz", + "integrity": "sha512-/XYrW4ZEWyqDvnXVKbgTXItpJOp2ycswk+fJ3vuexyolO6NSs0UuYC6X4f+FbHYL5VuWqVBv7EavGa+tB6sl3A==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.0.0" } }, - "node_modules/ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", - "dev": true, + "node_modules/@tiptap/extension-link": { + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/@tiptap/extension-link/-/extension-link-2.1.12.tgz", + "integrity": "sha512-Sti5hhlkCqi5vzdQjU/gbmr8kb578p+u0J4kWS+SSz3BknNThEm/7Id67qdjBTOQbwuN07lHjDaabJL0hSkzGQ==", "dependencies": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" + "linkifyjs": "^4.1.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.0.0", + "@tiptap/pm": "^2.0.0" } }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "dev": true - }, - "node_modules/electron-to-chromium": { - "version": "1.4.340", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.340.tgz", - "integrity": "sha512-zx8hqumOqltKsv/MF50yvdAlPF9S/4PXbyfzJS6ZGhbddGkRegdwImmfSVqCkEziYzrIGZ/TlrzBND4FysfkDg==" + "node_modules/@tiptap/extension-list-item": { + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/@tiptap/extension-list-item/-/extension-list-item-2.1.12.tgz", + "integrity": "sha512-Gk7hBFofAPmNQ8+uw8w5QSsZOMEGf7KQXJnx5B022YAUJTYYxO3jYVuzp34Drk9p+zNNIcXD4kc7ff5+nFOTrg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.0.0" + } }, - "node_modules/element-plus": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/element-plus/-/element-plus-2.3.1.tgz", - "integrity": "sha512-IBS7ic1mRyDXpOreRkredV4ByZSuax5HPb0zNOHm4qwKC4wm927yQv+Is0JbzxPzCW5zWaV4PLy9/Gl3E3v59w==", - "dependencies": { - "@ctrl/tinycolor": "^3.4.1", - "@element-plus/icons-vue": "^2.0.6", - "@floating-ui/dom": "^1.0.1", - "@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.7", - "@types/lodash": "^4.14.182", - "@types/lodash-es": "^4.17.6", - "@vueuse/core": "^9.1.0", - "async-validator": "^4.2.5", - "dayjs": "^1.11.3", - "escape-html": "^1.0.3", - "lodash": "^4.17.21", - "lodash-es": "^4.17.21", - "lodash-unified": "^1.0.2", - "memoize-one": "^6.0.0", - "normalize-wheel-es": "^1.2.0" + "node_modules/@tiptap/extension-ordered-list": { + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/@tiptap/extension-ordered-list/-/extension-ordered-list-2.1.12.tgz", + "integrity": "sha512-tF6VGl+D2avCgn9U/2YLJ8qVmV6sPE/iEzVAFZuOSe6L0Pj7SQw4K6AO640QBob/d8VrqqJFHCb6l10amJOnXA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "vue": "^3.2.0" + "@tiptap/core": "^2.0.0" } }, - "node_modules/element-resize-detector": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/element-resize-detector/-/element-resize-detector-1.2.4.tgz", - "integrity": "sha512-Fl5Ftk6WwXE0wqCgNoseKWndjzZlDCwuPTcoVZfCP9R3EHQF8qUtr3YUPNETegRBOKqQKPW3n4kiIWngGi8tKg==", + "node_modules/@tiptap/extension-paragraph": { + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/@tiptap/extension-paragraph/-/extension-paragraph-2.1.12.tgz", + "integrity": "sha512-hoH/uWPX+KKnNAZagudlsrr4Xu57nusGekkJWBcrb5MCDE91BS+DN2xifuhwXiTHxnwOMVFjluc0bPzQbkArsw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.0.0" + } + }, + "node_modules/@tiptap/extension-placeholder": { + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/@tiptap/extension-placeholder/-/extension-placeholder-2.1.12.tgz", + "integrity": "sha512-K52o7B1zkP4vaVy3z4ZwHn+tQy6KlXtedj1skLg+796ImwH2GYS5z6MFOTfKzBO2hLncUzLco/s0C5PLCD6SDw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.0.0", + "@tiptap/pm": "^2.0.0" + } + }, + "node_modules/@tiptap/extension-strike": { + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/@tiptap/extension-strike/-/extension-strike-2.1.12.tgz", + "integrity": "sha512-HlhrzIjYUT8oCH9nYzEL2QTTn8d1ECnVhKvzAe6x41xk31PjLMHTUy8aYjeQEkWZOWZ34tiTmslV1ce6R3Dt8g==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.0.0" + } + }, + "node_modules/@tiptap/extension-text": { + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/@tiptap/extension-text/-/extension-text-2.1.12.tgz", + "integrity": "sha512-rCNUd505p/PXwU9Jgxo4ZJv4A3cIBAyAqlx/dtcY6cjztCQuXJhuQILPhjGhBTOLEEL4kW2wQtqzCmb7O8i2jg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.0.0" + } + }, + "node_modules/@tiptap/pm": { + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-2.1.12.tgz", + "integrity": "sha512-Q3MXXQABG4CZBesSp82yV84uhJh/W0Gag6KPm2HRWPimSFELM09Z9/5WK9RItAYE0aLhe4Krnyiczn9AAa1tQQ==", "dependencies": { - "batch-processor": "1.0.0" + "prosemirror-changeset": "^2.2.0", + "prosemirror-collab": "^1.3.0", + "prosemirror-commands": "^1.3.1", + "prosemirror-dropcursor": "^1.5.0", + "prosemirror-gapcursor": "^1.3.1", + "prosemirror-history": "^1.3.0", + "prosemirror-inputrules": "^1.2.0", + "prosemirror-keymap": "^1.2.0", + "prosemirror-markdown": "^1.10.1", + "prosemirror-menu": "^1.2.1", + "prosemirror-model": "^1.18.1", + "prosemirror-schema-basic": "^1.2.0", + "prosemirror-schema-list": "^1.2.2", + "prosemirror-state": "^1.4.1", + "prosemirror-tables": "^1.3.0", + "prosemirror-trailing-node": "^2.0.2", + "prosemirror-transform": "^1.7.0", + "prosemirror-view": "^1.28.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" } }, - "node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + "node_modules/@tiptap/starter-kit": { + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/@tiptap/starter-kit/-/starter-kit-2.1.12.tgz", + "integrity": "sha512-+RoP1rWV7rSCit2+3wl2bjvSRiePRJE/7YNKbvH8Faz/+AMO23AFegHoUFynR7U0ouGgYDljGkkj35e0asbSDA==", + "dependencies": { + "@tiptap/core": "^2.1.12", + "@tiptap/extension-blockquote": "^2.1.12", + "@tiptap/extension-bold": "^2.1.12", + "@tiptap/extension-bullet-list": "^2.1.12", + "@tiptap/extension-code": "^2.1.12", + "@tiptap/extension-code-block": "^2.1.12", + "@tiptap/extension-document": "^2.1.12", + "@tiptap/extension-dropcursor": "^2.1.12", + "@tiptap/extension-gapcursor": "^2.1.12", + "@tiptap/extension-hard-break": "^2.1.12", + "@tiptap/extension-heading": "^2.1.12", + "@tiptap/extension-history": "^2.1.12", + "@tiptap/extension-horizontal-rule": "^2.1.12", + "@tiptap/extension-italic": "^2.1.12", + "@tiptap/extension-list-item": "^2.1.12", + "@tiptap/extension-ordered-list": "^2.1.12", + "@tiptap/extension-paragraph": "^2.1.12", + "@tiptap/extension-strike": "^2.1.12", + "@tiptap/extension-text": "^2.1.12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + } }, - "node_modules/emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "engines": { - "node": ">= 4" + "node_modules/@tiptap/vue-3": { + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/@tiptap/vue-3/-/vue-3-2.1.12.tgz", + "integrity": "sha512-yAcfmWw/9jtIUbhb0uGQVI9NoPYgHRasX2sAGWnm9Al+0aJktgmQ3mLCifXfXfjyEbeMF0p2L6Ul8tO7eho7aQ==", + "dependencies": { + "@tiptap/extension-bubble-menu": "^2.1.12", + "@tiptap/extension-floating-menu": "^2.1.12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.0.0", + "@tiptap/pm": "^2.0.0", + "vue": "^3.0.0" } }, - "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "node_modules/@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", "dev": true, "engines": { - "node": ">= 0.8" + "node": ">=10.13.0" } }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "node_modules/@types/aria-query": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", + "dev": true + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", "dev": true, "dependencies": { - "once": "^1.4.0" + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" } }, - "node_modules/engine.io-client": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.4.0.tgz", - "integrity": "sha512-GyKPDyoEha+XZ7iEqam49vz6auPnNJ9ZBfy89f+rMMas8AuiMWOZ9PVzu8xb9ZC6rafUqiGHSCfu22ih66E+1g==", + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, "dependencies": { - "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.3.1", - "engine.io-parser": "~5.0.3", - "ws": "~8.11.0", - "xmlhttprequest-ssl": "~2.0.0" + "@babel/types": "^7.0.0" } }, - "node_modules/engine.io-parser": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.6.tgz", - "integrity": "sha512-tjuoZDMAdEhVnSFleYPCtdL2GXwVTGtNjoeJd9IhIG3C1xs9uwxqRNEu5WpnDZCaozwVlK/nuQhpodhXSIMaxw==", - "engines": { - "node": ">=10.0.0" + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" } }, - "node_modules/enhanced-resolve": { - "version": "5.14.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.14.0.tgz", - "integrity": "sha512-+DCows0XNwLDcUhbFJPdlQEVnT2zXlCv7hPxemTz86/O+B/hCQ+mb7ydkPKiflpVraqLPCAfu7lDy+hBXueojw==", - "peer": true, + "node_modules/@types/babel__traverse": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.5.tgz", + "integrity": "sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==", + "dev": true, "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" + "@babel/types": "^7.20.7" } }, - "node_modules/enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "node_modules/@types/body-parser": { + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", "dev": true, "dependencies": { - "ansi-colors": "^4.1.1" - }, - "engines": { - "node": ">=8.6" + "@types/connect": "*", + "@types/node": "*" } }, - "node_modules/entities": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz", - "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "node_modules/@types/chai": { + "version": "4.3.11", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.11.tgz", + "integrity": "sha512-qQR1dr2rGIHYlJulmr8Ioq3De0Le9E4MJ5AiaeAETJJpndT1uUNHsGFK3L/UIu+rbkQSdj8J/w2bCsBZc/Y5fQ==", + "dev": true + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "dependencies": { + "@types/node": "*" } }, - "node_modules/es-abstract": { - "version": "1.21.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz", - "integrity": "sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==", + "node_modules/@types/cross-spawn": { + "version": "6.0.6", + "resolved": "https://registry.npmjs.org/@types/cross-spawn/-/cross-spawn-6.0.6.tgz", + "integrity": "sha512-fXRhhUkG4H3TQk5dBhQ7m/JDdSNHKwR2BBia62lhwEIq9xGiQKLxd6LymNhn47SjXhsUEPmxi+PKw2OkW4LLjA==", + "dev": true, "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-set-tostringtag": "^2.0.1", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.2.0", - "get-symbol-description": "^1.0.0", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "is-array-buffer": "^3.0.2", - "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.10", - "is-weakref": "^1.0.2", - "object-inspect": "^1.12.3", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", - "safe-regex-test": "^1.0.0", - "string.prototype.trim": "^1.2.7", - "string.prototype.trimend": "^1.0.6", - "string.prototype.trimstart": "^1.0.6", - "typed-array-length": "^1.0.4", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.9" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "@types/node": "*" } }, - "node_modules/es-get-iterator": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", - "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "node_modules/@types/detect-port": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/detect-port/-/detect-port-1.3.5.tgz", + "integrity": "sha512-Rf3/lB9WkDfIL9eEKaSYKc+1L/rNVYBjThk22JTqQw0YozXarX8YljFAz+HCoC6h4B4KwCMsBPZHaFezwT4BNA==", + "dev": true + }, + "node_modules/@types/doctrine": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@types/doctrine/-/doctrine-0.0.3.tgz", + "integrity": "sha512-w5jZ0ee+HaPOaX25X2/2oGR/7rgAQSYII7X7pp0m9KgBfMP7uKfMfTvcpl5Dj+eDBbpxKGiqE+flqDr6XTd2RA==", + "dev": true + }, + "node_modules/@types/ejs": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@types/ejs/-/ejs-3.1.5.tgz", + "integrity": "sha512-nv+GSx77ZtXiJzwKdsASqi+YQ5Z7vwHsTP0JY2SiQgjGckkBRKZnk8nIM+7oUZ1VCtuTz0+By4qVR7fqzp/Dfg==", + "dev": true + }, + "node_modules/@types/emscripten": { + "version": "1.39.10", + "resolved": "https://registry.npmjs.org/@types/emscripten/-/emscripten-1.39.10.tgz", + "integrity": "sha512-TB/6hBkYQJxsZHSqyeuO1Jt0AB/bW6G7rHt9g7lML7SOF6lbgcHvw/Lr+69iqN0qxgXLhWKScAon73JNnptuDw==", + "dev": true + }, + "node_modules/@types/eslint": { + "version": "8.21.3", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.21.3.tgz", + "integrity": "sha512-fa7GkppZVEByMWGbTtE5MbmXWJTVbrjjaS8K6uQj+XtuuUv1fsuPAxhygfqLmsb/Ufb3CV8deFCpiMfAgi00Sw==", + "peer": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "has-symbols": "^1.0.3", - "is-arguments": "^1.1.1", - "is-map": "^2.0.2", - "is-set": "^2.0.2", - "is-string": "^1.0.7", - "isarray": "^2.0.5", - "stop-iteration-iterator": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "@types/estree": "*", + "@types/json-schema": "*" } }, - "node_modules/es-module-lexer": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.2.1.tgz", - "integrity": "sha512-9978wrXM50Y4rTMmW5kXIC09ZdXQZqkE4mxhwkd8VbzsGkXGPgV4zWuqQJgCEzYngdo2dYDa0l8xhX4fkSwJSg==", - "peer": true - }, - "node_modules/es-set-tostringtag": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", - "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "node_modules/@types/eslint-scope": { + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", + "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", + "peer": true, "dependencies": { - "get-intrinsic": "^1.1.3", - "has": "^1.0.3", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" + "@types/eslint": "*", + "@types/estree": "*" } }, - "node_modules/es-shim-unscopables": { + "node_modules/@types/estree": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", - "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz", + "integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==" + }, + "node_modules/@types/express": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "dev": true, "dependencies": { - "has": "^1.0.3" + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" } }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "node_modules/@types/express-serve-static-core": { + "version": "4.17.41", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.41.tgz", + "integrity": "sha512-OaJ7XLaelTgrvlZD8/aa0vvvxZdUmlCn6MtWeB7TkiKW70BQLc9XEPpDLPdbo52ZhXUCrznlWdCHWxJWtdyajA==", + "dev": true, "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" } }, - "node_modules/esbuild": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.17.tgz", - "integrity": "sha512-1GJtYnUxsJreHYA0Y+iQz2UEykonY66HNWOb0yXYZi9/kNrORUEHVg87eQsCtqh59PEJ5YVZJO98JHznMJSWjg==", - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/android-arm": "0.18.17", - "@esbuild/android-arm64": "0.18.17", - "@esbuild/android-x64": "0.18.17", - "@esbuild/darwin-arm64": "0.18.17", - "@esbuild/darwin-x64": "0.18.17", - "@esbuild/freebsd-arm64": "0.18.17", - "@esbuild/freebsd-x64": "0.18.17", - "@esbuild/linux-arm": "0.18.17", - "@esbuild/linux-arm64": "0.18.17", - "@esbuild/linux-ia32": "0.18.17", - "@esbuild/linux-loong64": "0.18.17", - "@esbuild/linux-mips64el": "0.18.17", - "@esbuild/linux-ppc64": "0.18.17", - "@esbuild/linux-riscv64": "0.18.17", - "@esbuild/linux-s390x": "0.18.17", - "@esbuild/linux-x64": "0.18.17", - "@esbuild/netbsd-x64": "0.18.17", - "@esbuild/openbsd-x64": "0.18.17", - "@esbuild/sunos-x64": "0.18.17", - "@esbuild/win32-arm64": "0.18.17", - "@esbuild/win32-ia32": "0.18.17", - "@esbuild/win32-x64": "0.18.17" - } + "node_modules/@types/find-cache-dir": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@types/find-cache-dir/-/find-cache-dir-3.2.1.tgz", + "integrity": "sha512-frsJrz2t/CeGifcu/6uRo4b+SzAwT4NYCVPu1GN8IB9XTzrpPkGuV0tmh9mN+/L0PklAlsC3u5Fxt0ju00LXIw==", + "dev": true }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "engines": { - "node": ">=6" + "node_modules/@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "dev": true, + "dependencies": { + "@types/node": "*" } }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + "node_modules/@types/http-errors": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", + "dev": true }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "engines": { - "node": ">=0.8.0" - } + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "dev": true }, - "node_modules/eslint": { - "version": "8.36.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.36.0.tgz", - "integrity": "sha512-Y956lmS7vDqomxlaaQAHVmeb4tNMp2FWIvU/RnU5BD3IKMD/MJPr76xdyr68P8tV1iNMvN2mRK0yy3c+UjL+bw==", + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "dev": true, "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.0.1", - "@eslint/js": "8.36.0", - "@humanwhocodes/config-array": "^0.11.8", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.5.0", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "grapheme-splitter": "^1.0.4", - "ignore": "^5.2.0", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-sdsl": "^4.1.4", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "@types/istanbul-lib-coverage": "*" } }, - "node_modules/eslint-config-airbnb-base": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz", - "integrity": "sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==", + "node_modules/@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "dev": true, "dependencies": { - "confusing-browser-globals": "^1.0.10", - "object.assign": "^4.1.2", - "object.entries": "^1.1.5", - "semver": "^6.3.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "peerDependencies": { - "eslint": "^7.32.0 || ^8.2.0", - "eslint-plugin-import": "^2.25.2" + "@types/istanbul-lib-report": "*" } }, - "node_modules/eslint-import-resolver-alias": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-alias/-/eslint-import-resolver-alias-1.1.2.tgz", - "integrity": "sha512-WdviM1Eu834zsfjHtcGHtGfcu+F30Od3V7I9Fi57uhBEwPkjDcii7/yW8jAT+gOhn4P/vOxxNAXbFAKsrrc15w==", - "engines": { - "node": ">= 4" - }, - "peerDependencies": { - "eslint-plugin-import": ">=1.4.0" + "node_modules/@types/json-schema": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==" + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==" + }, + "node_modules/@types/lodash": { + "version": "4.14.191", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.191.tgz", + "integrity": "sha512-BdZ5BCCvho3EIXw6wUCXHe7rS53AIDPLE+JzwgT+OsJk53oBfbSmZZ7CX4VaRoN78N+TJpFi9QPlfIVNmJYWxQ==" + }, + "node_modules/@types/lodash-es": { + "version": "4.17.7", + "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.7.tgz", + "integrity": "sha512-z0ptr6UI10VlU6l5MYhGwS4mC8DZyYer2mCoyysZtSF7p26zOX8UpbrV0YpNYLGS8K4PUFIyEr62IMFFjveSiQ==", + "dependencies": { + "@types/lodash": "*" } }, - "node_modules/eslint-import-resolver-custom-alias": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-custom-alias/-/eslint-import-resolver-custom-alias-1.3.0.tgz", - "integrity": "sha512-9rrpduF6/SZHFXrJgjeA+edJek6xulplYfo/UJvLPrY38O9UY00rAq76dHRnZ289yftc5NIfx3THi0IILRQ3dg==", + "node_modules/@types/mdx": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.10.tgz", + "integrity": "sha512-Rllzc5KHk0Al5/WANwgSPl1/CwjqCy+AZrGd78zuK+jO9aDM6ffblZ+zIjgPNAaEBmlO0RYDvLNh7wD0zKVgEg==", + "dev": true + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true + }, + "node_modules/@types/mime-types": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@types/mime-types/-/mime-types-2.1.4.tgz", + "integrity": "sha512-lfU4b34HOri+kAY5UheuFMWPDOI+OPceBSHZKp69gEyTL/mmJ4cnU6Y/rlme3UL3GyOn6Y42hyIEw0/q8sWx5w==", + "dev": true + }, + "node_modules/@types/node": { + "version": "14.18.41", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.41.tgz", + "integrity": "sha512-2cfHr8AsUjKx6u4Q+d2eqK51z8+HueoumCQGCKVt95y/yGG4uajOuCANSnE20mbLw94h3tMcddIJ8nYkTu2mFw==" + }, + "node_modules/@types/node-fetch": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.11.tgz", + "integrity": "sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==", + "dev": true, "dependencies": { - "glob-parent": "^5.1.0", - "resolve": "^1.3.0" - }, - "peerDependencies": { - "eslint-plugin-import": ">=2.2.0" + "@types/node": "*", + "form-data": "^4.0.0" } }, - "node_modules/eslint-import-resolver-custom-alias/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "node_modules/@types/node-fetch/node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, "dependencies": { - "is-glob": "^4.0.1" + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" }, "engines": { "node": ">= 6" } }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz", - "integrity": "sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==", + "node_modules/@types/normalize-package-data": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", + "dev": true + }, + "node_modules/@types/object.omit": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/object.omit/-/object.omit-3.0.0.tgz", + "integrity": "sha512-I27IoPpH250TUzc9FzXd0P1BV/BMJuzqD3jOz98ehf9dQqGkxlq+hO1bIqZGWqCg5bVOy0g4AUVJtnxe0klDmw==" + }, + "node_modules/@types/object.pick": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/object.pick/-/object.pick-1.3.2.tgz", + "integrity": "sha512-sn7L+qQ6RLPdXRoiaE7bZ/Ek+o4uICma/lBFPyJEKDTPTBP1W8u0c4baj3EiS4DiqLs+Hk+KUGvMVJtAw3ePJg==" + }, + "node_modules/@types/pluralize": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/@types/pluralize/-/pluralize-0.0.33.tgz", + "integrity": "sha512-JOqsl+ZoCpP4e8TDke9W79FDcSgPAR0l6pixx2JHkhnRjvShyYiAYw2LVsnA7K08Y6DeOnaU6ujmENO4os/cYg==", + "dev": true + }, + "node_modules/@types/pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha512-nj39q0wAIdhwn7DGUyT9irmsKK1tV0bd5WFEhgpqNTMFZ8cE+jieuTphCW0tfdm47S2zVT5mr09B28b1chmQMA==", + "dev": true + }, + "node_modules/@types/prop-types": { + "version": "15.7.11", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz", + "integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==", + "dev": true + }, + "node_modules/@types/qs": { + "version": "6.9.11", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.11.tgz", + "integrity": "sha512-oGk0gmhnEJK4Yyk+oI7EfXsLayXatCWPHary1MtcmbAifkobT9cM9yutG/hZKIseOU0MqbIwQ/u2nn/Gb+ltuQ==", + "dev": true + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true + }, + "node_modules/@types/react": { + "version": "18.2.48", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.48.tgz", + "integrity": "sha512-qboRCl6Ie70DQQG9hhNREz81jqC1cs9EVNcjQ1AU+jH6NFfSAhVVbrrY/+nSF+Bsk4AOwm9Qa61InvMCyV+H3w==", + "dev": true, "dependencies": { - "debug": "^3.2.7", - "is-core-module": "^2.11.0", - "resolve": "^1.22.1" + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" } }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "node_modules/@types/scheduler": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz", + "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==", + "dev": true + }, + "node_modules/@types/semver": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", + "dev": true + }, + "node_modules/@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "dev": true, "dependencies": { - "ms": "^2.1.1" + "@types/mime": "^1", + "@types/node": "*" } }, - "node_modules/eslint-module-utils": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz", - "integrity": "sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==", + "node_modules/@types/serve-static": { + "version": "1.15.5", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.5.tgz", + "integrity": "sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ==", + "dev": true, "dependencies": { - "debug": "^3.2.7" - }, - "engines": { - "node": ">=4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } + "@types/http-errors": "*", + "@types/mime": "*", + "@types/node": "*" } }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "node_modules/@types/sinonjs__fake-timers": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz", + "integrity": "sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g==", + "dev": true + }, + "node_modules/@types/sizzle": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz", + "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==", + "dev": true + }, + "node_modules/@types/throttle-debounce": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/throttle-debounce/-/throttle-debounce-2.1.0.tgz", + "integrity": "sha512-5eQEtSCoESnh2FsiLTxE121IiE60hnMqcb435fShf4bpLRjEu1Eoekht23y6zXS9Ts3l+Szu3TARnTsA0GkOkQ==" + }, + "node_modules/@types/unist": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", + "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", + "dev": true + }, + "node_modules/@types/uuid": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.7.tgz", + "integrity": "sha512-WUtIVRUZ9i5dYXefDEAI7sh9/O7jGvHg7Df/5O/gtH3Yabe5odI3UWopVR1qbPXQtvOxWu3mM4XxlYeZtMWF4g==", + "dev": true + }, + "node_modules/@types/web-bluetooth": { + "version": "0.0.16", + "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz", + "integrity": "sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==" + }, + "node_modules/@types/yargs": { + "version": "17.0.23", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.23.tgz", + "integrity": "sha512-yuogunc04OnzGQCrfHx+Kk883Q4X0aSwmYZhKjI21m+SVYzjIbrWl8dOOwSv5hf2Um2pdCOXWo9isteZTNXUZQ==", + "dev": true, "dependencies": { - "ms": "^2.1.1" + "@types/yargs-parser": "*" } }, - "node_modules/eslint-plugin-cypress": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-cypress/-/eslint-plugin-cypress-2.12.1.tgz", - "integrity": "sha512-c2W/uPADl5kospNDihgiLc7n87t5XhUbFDoTl6CfVkmG+kDAb5Ux10V9PoLPu9N+r7znpc+iQlcmAqT1A/89HA==", + "node_modules/@types/yargs-parser": { + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", + "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", + "dev": true + }, + "node_modules/@types/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==", "dev": true, + "optional": true, "dependencies": { - "globals": "^11.12.0" - }, - "peerDependencies": { - "eslint": ">= 3.2.1" + "@types/node": "*" } }, - "node_modules/eslint-plugin-import": { - "version": "2.27.5", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz", - "integrity": "sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==", + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.5.tgz", + "integrity": "sha512-feA9xbVRWJZor+AnLNAr7A8JRWeZqHUf4T9tlP+TN04b05pFVhO5eN7/O93Y/1OUlLMHKbnJisgDURs/qvtqdg==", + "dev": true, "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flat": "^1.3.1", - "array.prototype.flatmap": "^1.3.1", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.7", - "eslint-module-utils": "^2.7.4", - "has": "^1.0.3", - "is-core-module": "^2.11.0", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.values": "^1.1.6", - "resolve": "^1.22.1", - "semver": "^6.3.0", - "tsconfig-paths": "^3.14.1" + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.59.5", + "@typescript-eslint/type-utils": "5.59.5", + "@typescript-eslint/utils": "5.59.5", + "debug": "^4.3.4", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" }, "engines": { - "node": ">=4" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" - } - }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dependencies": { - "ms": "^2.1.1" + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, "dependencies": { - "esutils": "^2.0.2" + "yallist": "^4.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=10" } }, - "node_modules/eslint-plugin-jsx-a11y": { - "version": "6.7.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.7.1.tgz", - "integrity": "sha512-63Bog4iIethyo8smBklORknVjB0T2dwB8Mr/hIC+fBS0uyHdYYpzM/Ed+YC8VxTjlXHEWFOdmgwcDn1U2L9VCA==", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==", + "dev": true, "dependencies": { - "@babel/runtime": "^7.20.7", - "aria-query": "^5.1.3", - "array-includes": "^3.1.6", - "array.prototype.flatmap": "^1.3.1", - "ast-types-flow": "^0.0.7", - "axe-core": "^4.6.2", - "axobject-query": "^3.1.1", - "damerau-levenshtein": "^1.0.8", - "emoji-regex": "^9.2.2", - "has": "^1.0.3", - "jsx-ast-utils": "^3.3.3", - "language-tags": "=1.0.5", - "minimatch": "^3.1.2", - "object.entries": "^1.1.6", - "object.fromentries": "^2.0.6", - "semver": "^6.3.0" + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">=4.0" + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" }, "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" } }, - "node_modules/eslint-plugin-react": { - "version": "7.32.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.32.2.tgz", - "integrity": "sha512-t2fBMa+XzonrrNkyVirzKlvn5RXzzPwRHtMvLAtVZrt8oxgnTQaYbU6SXTOO1mwQgp1y5+toMSKInnzGr0Knqg==", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/@typescript-eslint/parser": { + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.5.tgz", + "integrity": "sha512-NJXQC4MRnF9N9yWqQE2/KLRSOLvrrlZb48NGVfBa+RuPMN6B7ZcK5jZOvhuygv4D64fRKnZI4L4p8+M+rfeQuw==", + "dev": true, "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flatmap": "^1.3.1", - "array.prototype.tosorted": "^1.1.1", - "doctrine": "^2.1.0", - "estraverse": "^5.3.0", - "jsx-ast-utils": "^2.4.1 || ^3.0.0", - "minimatch": "^3.1.2", - "object.entries": "^1.1.6", - "object.fromentries": "^2.0.6", - "object.hasown": "^1.1.2", - "object.values": "^1.1.6", - "prop-types": "^15.8.1", - "resolve": "^2.0.0-next.4", - "semver": "^6.3.0", - "string.prototype.matchall": "^4.0.8" + "@typescript-eslint/scope-manager": "5.59.5", + "@typescript-eslint/types": "5.59.5", + "@typescript-eslint/typescript-estree": "5.59.5", + "debug": "^4.3.4" }, "engines": { - "node": ">=4" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/eslint-plugin-react/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.5.tgz", + "integrity": "sha512-jVecWwnkX6ZgutF+DovbBJirZcAxgxC0EOHYt/niMROf8p4PwxxG32Qdhj/iIQQIuOflLjNkxoXyArkcIP7C3A==", + "dev": true, "dependencies": { - "esutils": "^2.0.2" + "@typescript-eslint/types": "5.59.5", + "@typescript-eslint/visitor-keys": "5.59.5" }, "engines": { - "node": ">=0.10.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/eslint-plugin-react/node_modules/resolve": { - "version": "2.0.0-next.4", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz", - "integrity": "sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==", + "node_modules/@typescript-eslint/type-utils": { + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.5.tgz", + "integrity": "sha512-4eyhS7oGym67/pSxA2mmNq7X164oqDYNnZCUayBwJZIRVvKpBCMBzFnFxjeoDeShjtO6RQBHBuwybuX3POnDqg==", + "dev": true, "dependencies": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" + "@typescript-eslint/typescript-estree": "5.59.5", + "@typescript-eslint/utils": "5.59.5", + "debug": "^4.3.4", + "tsutils": "^3.21.0" }, - "bin": { - "resolve": "bin/resolve" + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/eslint-plugin-vue": { - "version": "9.10.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.10.0.tgz", - "integrity": "sha512-2MgP31OBf8YilUvtakdVMc8xVbcMp7z7/iQj8LHVpXrSXHPXSJRUIGSPFI6b6pyCx/buKaFJ45ycqfHvQRiW2g==", + "node_modules/@typescript-eslint/type-utils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/@typescript-eslint/type-utils/node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, "dependencies": { - "@eslint-community/eslint-utils": "^4.3.0", - "natural-compare": "^1.4.0", - "nth-check": "^2.0.1", - "postcss-selector-parser": "^6.0.9", - "semver": "^7.3.5", - "vue-eslint-parser": "^9.0.1", - "xml-name-validator": "^4.0.0" + "tslib": "^1.8.1" }, "engines": { - "node": "^14.17.0 || >=16.0.0" + "node": ">= 6" }, "peerDependencies": { - "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0" + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" } }, - "node_modules/eslint-plugin-vue/node_modules/lru-cache": { + "node_modules/@typescript-eslint/types": { + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.5.tgz", + "integrity": "sha512-xkfRPHbqSH4Ggx4eHRIO/eGL8XL4Ysb4woL8c87YuAo8Md7AUjyWKa9YMwTL519SyDPrfEgKdewjkxNCVeJW7w==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.5.tgz", + "integrity": "sha512-+XXdLN2CZLZcD/mO7mQtJMvCkzRfmODbeSKuMY/yXbGkzvA9rJyDY5qDYNoiz2kP/dmyAxXquL2BvLQLJFPQIg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.59.5", + "@typescript-eslint/visitor-keys": "5.59.5", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -5811,10 +7142,11 @@ "node": ">=10" } }, - "node_modules/eslint-plugin-vue/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==", + "dev": true, "dependencies": { "lru-cache": "^6.0.0" }, @@ -5825,878 +7157,975 @@ "node": ">=10" } }, - "node_modules/eslint-plugin-vue/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "node_modules/@typescript-eslint/typescript-estree/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true }, - "node_modules/eslint-plugin-vuejs-accessibility": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-vuejs-accessibility/-/eslint-plugin-vuejs-accessibility-1.2.0.tgz", - "integrity": "sha512-wF7kT22lS2VOmIpDeI65bnFFKFgESEEpI+CWKr43mdfDRywA4sCk7cKhtZsvfbPOtKO0GDlnpFxZbOIGsFn7IQ==", + "node_modules/@typescript-eslint/typescript-estree/node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, "dependencies": { - "aria-query": "^5.0.0", - "emoji-regex": "^10.0.0", - "vue-eslint-parser": "^9.0.1" + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" }, "peerDependencies": { - "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" } }, - "node_modules/eslint-plugin-vuejs-accessibility/node_modules/emoji-regex": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.2.1.tgz", - "integrity": "sha512-97g6QgOk8zlDRdgq1WxwgTMgEWGVAQvB5Fdpgc1MkNy56la5SKP9GsMXKDOdqwn90/41a8yPwIGk1Y6WVbeMQA==" + "node_modules/@typescript-eslint/typescript-estree/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, - "node_modules/eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "node_modules/@typescript-eslint/utils": { + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.5.tgz", + "integrity": "sha512-sCEHOiw+RbyTii9c3/qN74hYDPNORb8yWCoPLmB7BIflhplJ65u2PBpdRla12e3SSTJ2erRkPjz7ngLHhUegxA==", + "dev": true, "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.59.5", + "@typescript-eslint/types": "5.59.5", + "@typescript-eslint/typescript-estree": "5.59.5", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "node_modules/@typescript-eslint/utils/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=8.0.0" } }, - "node_modules/eslint/node_modules/ansi-styles": { + "node_modules/@typescript-eslint/utils/node_modules/estraverse": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": { - "color-convert": "^2.0.1" - }, + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=4.0" } }, - "node_modules/eslint/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/@typescript-eslint/utils/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "yallist": "^4.0.0" }, "engines": { "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/eslint/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/@typescript-eslint/utils/node_modules/semver": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==", + "dev": true, "dependencies": { - "color-name": "~1.1.4" + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">=7.0.0" + "node": ">=10" } }, - "node_modules/eslint/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/eslint/node_modules/escape-string-regexp": { + "node_modules/@typescript-eslint/utils/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, - "node_modules/eslint/node_modules/globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.5.tgz", + "integrity": "sha512-qL+Oz+dbeBRTeyJTIy0eniD3uvqU7x+y1QceBismZ41hd4aBSRh8UAw4pZP0+XzLuPZmx4raNMq/I+59W2lXKA==", + "dev": true, "dependencies": { - "type-fest": "^0.20.2" + "@typescript-eslint/types": "5.59.5", + "eslint-visitor-keys": "^3.3.0" }, "engines": { - "node": ">=8" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/eslint/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==", + "node_modules/@vitejs/plugin-vue": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-4.2.3.tgz", + "integrity": "sha512-R6JDUfiZbJA9cMiguQ7jxALsgiprjBeHL5ikpXfJCH62pPHtI+JdJ5xWj6Ev73yXSlYl86+blXn1kZHQ7uElxw==", "engines": { - "node": ">=8" + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.0.0", + "vue": "^3.2.25" } }, - "node_modules/eslint/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/@vitest/expect": { + "version": "0.34.7", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-0.34.7.tgz", + "integrity": "sha512-G9iEtwrD6ZQ4MVHZufif9Iqz3eLtuwBBNx971fNAGPaugM7ftAWjQN+ob2zWhtzURp8RK3zGXOxVb01mFo3zAQ==", + "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "@vitest/spy": "0.34.7", + "@vitest/utils": "0.34.7", + "chai": "^4.3.10" }, - "engines": { - "node": ">=8" + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/eslint/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "engines": { - "node": ">=10" + "node_modules/@vitest/spy": { + "version": "0.34.7", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-0.34.7.tgz", + "integrity": "sha512-NMMSzOY2d8L0mcOt4XcliDOS1ISyGlAXuQtERWVOoVHnKwmG+kKhinAiGw3dTtMQWybfa89FG8Ucg9tiC/FhTQ==", + "dev": true, + "dependencies": { + "tinyspy": "^2.1.1" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/vitest" } }, - "node_modules/espree": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.0.tgz", - "integrity": "sha512-JPbJGhKc47++oo4JkEoTe2wjy4fmMwvFpgJT9cQzmfXKp22Dr6Hf1tdCteLz1h0P3t+mGvWZ+4Uankvh8+c6zw==", + "node_modules/@vitest/utils": { + "version": "0.34.7", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-0.34.7.tgz", + "integrity": "sha512-ziAavQLpCYS9sLOorGrFFKmy2gnfiNU0ZJ15TsMz/K92NAPS/rp9K4z6AJQQk5Y8adCy4Iwpxy7pQumQ/psnRg==", + "dev": true, "dependencies": { - "acorn": "^8.8.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "diff-sequences": "^29.4.3", + "loupe": "^2.3.6", + "pretty-format": "^29.5.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://opencollective.com/vitest" } }, - "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dependencies": { - "estraverse": "^5.1.0" - }, + "node_modules/@vitest/utils/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, "engines": { - "node": ">=0.10" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "node_modules/@vitest/utils/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, "dependencies": { - "estraverse": "^5.2.0" + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" }, "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "engines": { - "node": ">=0.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/eventemitter2": { - "version": "6.4.7", - "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.7.tgz", - "integrity": "sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg==", + "node_modules/@vitest/utils/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "peer": true, - "engines": { - "node": ">=0.8.x" + "node_modules/@vue/compiler-core": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.3.1.tgz", + "integrity": "sha512-5le1qYSBgLWg2jdLrbydlhnPJkkzMw46UrRUvTnOKlfg6pThtm9ohhqBhNPHbr0RcM1MCbK5WZe/3Ghz0SZjpQ==", + "dependencies": { + "@babel/parser": "^7.21.3", + "@vue/shared": "3.3.1", + "estree-walker": "^2.0.2", + "source-map-js": "^1.0.2" } }, - "node_modules/executable": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/executable/-/executable-4.1.1.tgz", - "integrity": "sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==", - "dev": true, + "node_modules/@vue/compiler-dom": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.3.1.tgz", + "integrity": "sha512-VmgIsoLivCft3+oNc5KM7b9wd0nZxP/g2qilMwi1hJyGA624KWnNKHn4hzBQs4FpzydUVpNy+TWVT8KiRCh3MQ==", "dependencies": { - "pify": "^2.2.0" - }, - "engines": { - "node": ">=4" + "@vue/compiler-core": "3.3.1", + "@vue/shared": "3.3.1" } }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "node_modules/extract-zip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", - "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", - "dev": true, + "node_modules/@vue/compiler-sfc": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.3.1.tgz", + "integrity": "sha512-G+FPwBbXSLaA4+Ry5/bdD9Oda+sRslQcE9o6JSZaougRiT4OjVL0vtkbQHPrGRTULZV28OcrAjRfSZOSB0OTXQ==", "dependencies": { - "debug": "^4.1.1", - "get-stream": "^5.1.0", - "yauzl": "^2.10.0" - }, - "bin": { - "extract-zip": "cli.js" - }, - "engines": { - "node": ">= 10.17.0" - }, - "optionalDependencies": { - "@types/yauzl": "^2.9.1" + "@babel/parser": "^7.20.15", + "@vue/compiler-core": "3.3.1", + "@vue/compiler-dom": "3.3.1", + "@vue/compiler-ssr": "3.3.1", + "@vue/reactivity-transform": "3.3.1", + "@vue/shared": "3.3.1", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.0", + "postcss": "^8.1.10", + "source-map-js": "^1.0.2" } }, - "node_modules/extract-zip/node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, + "node_modules/@vue/compiler-ssr": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.3.1.tgz", + "integrity": "sha512-QOQWGNCWuSeyKx4KvWSJlnIMGg+/2oCHgkFUYo7aJ+9Uaaz45yRgKQ+FNigy50NYBQIhpXn2e4OSR8GXh4knrQ==", "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "@vue/compiler-dom": "3.3.1", + "@vue/shared": "3.3.1" } }, - "node_modules/extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", - "dev": true, - "engines": [ - "node >=0.6.0" - ] - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + "node_modules/@vue/devtools-api": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.5.0.tgz", + "integrity": "sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q==" }, - "node_modules/fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", - "dev": true, + "node_modules/@vue/eslint-config-airbnb": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@vue/eslint-config-airbnb/-/eslint-config-airbnb-7.0.0.tgz", + "integrity": "sha512-qC3HRnvaDWRocDKPVKUnjWLXo1NDfDSPKwizc49llN/mRZF2Q9D/7wcAMwzCVzPM/D80ZUz0sy1cq9u/6jFnqw==", "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "eslint-config-airbnb-base": "^15.0.0", + "eslint-import-resolver-custom-alias": "^1.3.0", + "eslint-import-resolver-node": "^0.3.6", + "eslint-plugin-import": "^2.26.0", + "eslint-plugin-jsx-a11y": "^6.6.1", + "eslint-plugin-react": "^7.30.1", + "eslint-plugin-vuejs-accessibility": "^1.2.0", + "vue-eslint-parser": "^9.0.3" }, - "engines": { - "node": ">=8.6.0" + "peerDependencies": { + "eslint": "^8.2.0", + "eslint-plugin-vue": "^9.2.0" } }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "node_modules/@vue/eslint-config-typescript": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@vue/eslint-config-typescript/-/eslint-config-typescript-11.0.3.tgz", + "integrity": "sha512-dkt6W0PX6H/4Xuxg/BlFj5xHvksjpSlVjtkQCpaYJBIEuKj2hOVU7r+TIe+ysCwRYFz/lGqvklntRkCAibsbPw==", "dev": true, "dependencies": { - "is-glob": "^4.0.1" + "@typescript-eslint/eslint-plugin": "^5.59.1", + "@typescript-eslint/parser": "^5.59.1", + "vue-eslint-parser": "^9.1.1" }, "engines": { - "node": ">= 6" + "node": "^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0", + "eslint-plugin-vue": "^9.0.0", + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" + "node_modules/@vue/reactivity": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.3.1.tgz", + "integrity": "sha512-zCfmazOtyUdC1NS/EPiSYJ4RqojqmTAviJyBbyVvY8zAv5NhK44Yfw0E1tt+m5vz0ZO1ptI9jDKBr3MWIEkpgw==", + "dependencies": { + "@vue/shared": "3.3.1" + } }, - "node_modules/fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "node_modules/@vue/reactivity-transform": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.3.1.tgz", + "integrity": "sha512-MkOrJauAGH4MNdxGW/PmrDegMyOGX0wGIdKUZJRBXOTpotDONg7/TPJe2QeGeBCow/5v9iOqZOWCfvmOWIaDMg==", "dependencies": { - "reusify": "^1.0.4" + "@babel/parser": "^7.20.15", + "@vue/compiler-core": "3.3.1", + "@vue/shared": "3.3.1", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.0" } }, - "node_modules/fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", - "dev": true, + "node_modules/@vue/runtime-core": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.3.1.tgz", + "integrity": "sha512-Ljb37LYafhQqKIasc0r32Cva8gIh6VeSMjlwO6V03tCjHd18gmjP0F4UD+8/a59sGTysAgA8Rb9lIC2DVxRz2Q==", "dependencies": { - "pend": "~1.2.0" + "@vue/reactivity": "3.3.1", + "@vue/shared": "3.3.1" } }, - "node_modules/figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dev": true, + "node_modules/@vue/runtime-dom": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.3.1.tgz", + "integrity": "sha512-NBjYbQPtMklb7lsJsM2Juv5Ygry6mvZP7PdH1GZqrzfLkvlplQT3qCtQMd/sib6yiy8t9m/Y4hVU7X9nzb9Oeg==", "dependencies": { - "escape-string-regexp": "^1.0.5" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "@vue/runtime-core": "3.3.1", + "@vue/shared": "3.3.1", + "csstype": "^3.1.1" } }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "node_modules/@vue/server-renderer": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.3.1.tgz", + "integrity": "sha512-sod8ggOwbkQXw3lBjfzrbdxRS9lw/lNHoMaXghHawNYowf+4WoaLWD5ouz6fPZadUqNKAsqK95p8DYb1vcVfPA==", "dependencies": { - "flat-cache": "^3.0.4" + "@vue/compiler-ssr": "3.3.1", + "@vue/shared": "3.3.1" }, - "engines": { - "node": "^10.12.0 || >=12.0.0" + "peerDependencies": { + "vue": "3.3.1" } }, - "node_modules/file-saver": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.2.tgz", - "integrity": "sha512-Wz3c3XQ5xroCxd1G8b7yL0Ehkf0TC9oYC6buPFkNnU9EnaPlifeAFCyCh+iewXTyFRcg0a6j3J7FmJsIhlhBdw==" + "node_modules/@vue/shared": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.3.1.tgz", + "integrity": "sha512-ybDBtQ+479HL/bkeIOIAwgpeAEACzztkvulJLbK3JMFuTOv4qDivmV3AIsR8RHYJ+RD9tQxcHWBsX4GqEcYrfw==" }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "devOptional": true, + "node_modules/@vuelidate/core": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@vuelidate/core/-/core-2.0.1.tgz", + "integrity": "sha512-seBfM7ZtQ+NzXEdJpwLPgX/GlY+R10VI3FSoXyEJH7p4kKcz06f5oloh2EDozCJVMxP0Um/FFcfjBCn8CtGNOQ==", "dependencies": { - "to-regex-range": "^5.0.1" + "vue-demi": "^0.13.11" }, - "engines": { - "node": ">=8" + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^2.0.0 || >=3.0.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } } }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" + "node_modules/@vuelidate/core/node_modules/vue-demi": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.11.tgz", + "integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==", + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" }, "engines": { - "node": ">=10" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } } }, - "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dependencies": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" + "node_modules/@vuelidate/validators": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@vuelidate/validators/-/validators-2.0.1.tgz", + "integrity": "sha512-rlu14xo+r36ri2VMY6kLLgzIc3RKEIEKiyq/Nwvft3h8izt6jcBqOlDPkQL1d9qxn9mr2nVBcNlMBFMDrHpp/A==", + "dependencies": { + "vue-demi": "^0.13.11" }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==" - }, - "node_modules/flush-promises": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/flush-promises/-/flush-promises-1.0.2.tgz", - "integrity": "sha512-G0sYfLQERwKz4+4iOZYQEZVpOt9zQrlItIxQAAYAWpfby3gbHrx0osCHz5RLl/XoXevXk0xoN4hDFky/VV9TrA==" - }, - "node_modules/follow-redirects": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^2.0.0 || >=3.0.0" }, "peerDependenciesMeta": { - "debug": { + "@vue/composition-api": { "optional": true } } }, - "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "dependencies": { - "is-callable": "^1.1.3" - } - }, - "node_modules/forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" + "node_modules/@vuelidate/validators/node_modules/vue-demi": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.11.tgz", + "integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==", + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" }, "engines": { - "node": ">= 0.12" - } - }, - "node_modules/fraction.js": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", - "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==", - "dev": true, - "engines": { - "node": "*" + "node": ">=12" }, "funding": { - "type": "patreon", - "url": "https://www.patreon.com/infusion" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "dev": true, - "engines": { - "node": ">= 0.6" + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } } }, - "node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, + "node_modules/@vueuse/core": { + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-9.13.0.tgz", + "integrity": "sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==", "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "@types/web-bluetooth": "^0.0.16", + "@vueuse/metadata": "9.13.0", + "@vueuse/shared": "9.13.0", + "vue-demi": "*" }, - "engines": { - "node": ">=10" + "funding": { + "url": "https://github.com/sponsors/antfu" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "node_modules/@vueuse/core/node_modules/vue-demi": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.11.tgz", + "integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==", "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "node_modules/function.prototype.name": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", - "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "functions-have-names": "^1.2.2" + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" }, "engines": { - "node": ">= 0.4" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } } }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "node_modules/@vueuse/metadata": { + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-9.13.0.tgz", + "integrity": "sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==", "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" + "url": "https://github.com/sponsors/antfu" } }, - "node_modules/get-intrinsic": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", - "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", + "node_modules/@vueuse/shared": { + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-9.13.0.tgz", + "integrity": "sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==", "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" + "vue-demi": "*" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/antfu" } }, - "node_modules/get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "node_modules/@vueuse/shared/node_modules/vue-demi": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.11.tgz", + "integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==", + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" }, "engines": { - "node": ">= 0.4" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } } }, - "node_modules/getos": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/getos/-/getos-3.2.1.tgz", - "integrity": "sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q==", - "dev": true, + "node_modules/@webassemblyjs/ast": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", + "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", + "peer": true, "dependencies": { - "async": "^3.2.0" + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" } }, - "node_modules/getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", - "dev": true, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", + "peer": true + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", + "peer": true + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", + "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==", + "peer": true + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "peer": true, "dependencies": { - "assert-plus": "^1.0.0" + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@xtuc/long": "4.2.2" } }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", + "peer": true + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", + "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", + "peer": true, "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6" } }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "peer": true, "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" + "@xtuc/ieee754": "^1.2.0" } }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "peer": true, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", "peer": true }, - "node_modules/global-dirs": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", - "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", - "dev": true, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", + "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", + "peer": true, "dependencies": { - "ini": "2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-opt": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6", + "@webassemblyjs/wast-printer": "1.11.6" } }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "engines": { - "node": ">=4" + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", + "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" } }, - "node_modules/globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", + "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", + "peer": true, "dependencies": { - "define-properties": "^1.1.3" + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", + "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", + "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "peer": true + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "peer": true + }, + "node_modules/@yarnpkg/esbuild-plugin-pnp": { + "version": "3.0.0-rc.15", + "resolved": "https://registry.npmjs.org/@yarnpkg/esbuild-plugin-pnp/-/esbuild-plugin-pnp-3.0.0-rc.15.tgz", + "integrity": "sha512-kYzDJO5CA9sy+on/s2aIW0411AklfCi8Ck/4QDivOqsMKpStZA2SsR+X27VTggGwpStWaLrjJcDcdDMowtG8MA==", + "dev": true, + "dependencies": { + "tslib": "^2.4.0" }, "engines": { - "node": ">= 0.4" + "node": ">=14.15.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "esbuild": ">=0.10.0" } }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "node_modules/@yarnpkg/fslib": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@yarnpkg/fslib/-/fslib-2.10.3.tgz", + "integrity": "sha512-41H+Ga78xT9sHvWLlFOZLIhtU6mTGZ20pZ29EiZa97vnxdohJD2AF42rCoAoWfqUz486xY6fhjMH+DYEM9r14A==", "dev": true, "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" + "@yarnpkg/libzip": "^2.3.0", + "tslib": "^1.13.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=12 <14 || 14.2 - 14.9 || >14.10.0" } }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "node_modules/@yarnpkg/fslib/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/@yarnpkg/libzip": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/libzip/-/libzip-2.3.0.tgz", + "integrity": "sha512-6xm38yGVIa6mKm/DUCF2zFFJhERh/QWp1ufm4cNUvxsONBmfPg8uZ9pZBdOmF6qFGr/HlT6ABBkCSx/dlEtvWg==", + "dev": true, "dependencies": { - "get-intrinsic": "^1.1.3" + "@types/emscripten": "^1.39.6", + "tslib": "^1.13.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=12 <14 || 14.2 - 14.9 || >14.10.0" } }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" - }, - "node_modules/grapheme-splitter": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", - "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==" + "node_modules/@yarnpkg/libzip/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, "dependencies": { - "function-bind": "^1.1.1" + "mime-types": "~2.1.34", + "negotiator": "0.6.3" }, "engines": { - "node": ">= 0.4.0" + "node": ">= 0.6" } }, - "node_modules/has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node_modules/acorn": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" } }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "engines": { - "node": ">=4" + "node_modules/acorn-import-assertions": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", + "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", + "peer": true, + "peerDependencies": { + "acorn": "^8" } }, - "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-node": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", + "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", + "dev": true, "dependencies": { - "get-intrinsic": "^1.1.1" + "acorn": "^7.0.0", + "acorn-walk": "^7.0.0", + "xtend": "^4.0.2" + } + }, + "node_modules/acorn-node/node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=0.4.0" } }, - "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "node_modules/acorn-node/node_modules/acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=0.4.0" } }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "node_modules/address": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/address/-/address-1.2.2.tgz", + "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==", + "dev": true, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 10.0.0" } }, - "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "node_modules/agent-base": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-5.1.1.tgz", + "integrity": "sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g==", + "dev": true, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, "dependencies": { - "has-symbols": "^1.0.2" + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/hash-sum": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-2.0.0.tgz", - "integrity": "sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==" + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } }, - "node_modules/http-assert": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/http-assert/-/http-assert-1.5.0.tgz", - "integrity": "sha512-uPpH7OKX4H25hBmU6G1jWNaqJGpTXxey+YOUizJUAgu0AjLUeC8D73hTrhvDS5D+GJN1DN1+hhc/eF/wpxtp0w==", + "node_modules/ajv-formats/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", "dev": true, "dependencies": { - "deep-equal": "~1.0.1", - "http-errors": "~1.8.0" + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" }, - "engines": { - "node": ">= 0.8" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/http-assert/node_modules/deep-equal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", - "integrity": "sha512-bHtC0iYvWhyaTzvV3CZgPeZQqCOBGyGsVV7v4eevpdkLHfiSrXUdBG+qAuSz4RI70sszvjQ1QSZ98An1yNwpSw==", + "node_modules/ajv-formats/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true }, - "node_modules/http-errors": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", - "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", "dev": true, "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.1" + "type-fest": "^0.21.3" }, "engines": { - "node": ">= 0.6" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/http-signature": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.3.6.tgz", - "integrity": "sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==", - "dev": true, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^2.0.2", - "sshpk": "^1.14.1" + "color-convert": "^1.9.0" }, "engines": { - "node": ">=0.10" + "node": ">=4" } }, - "node_modules/human-signals": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", - "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", - "dev": true, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "devOptional": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, "engines": { - "node": ">=8.12.0" + "node": ">= 8" } }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "node_modules/app-root-dir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/app-root-dir/-/app-root-dir-1.0.2.tgz", + "integrity": "sha512-jlpIfsOoNoafl92Sz//64uQHGSyMrD2vYG5d8o2a4qGvyNCvXur7bzIsWtAC/6flI2RYAp3kv8rsfBtaLm7w0g==", + "dev": true + }, + "node_modules/arch": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", + "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", "dev": true, "funding": [ { @@ -6713,146 +8142,91 @@ } ] }, - "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", - "engines": { - "node": ">= 4" - } - }, - "node_modules/immutable": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.0.tgz", - "integrity": "sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg==", - "devOptional": true - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "engines": { - "node": ">=0.8.19" - } + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "node_modules/aria-hidden": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.3.tgz", + "integrity": "sha512-xcLxITLe2HYa1cnYnwCjkOO1PqUHQpozB8x9AR0OgWN2woOBi5kSDVxKfd0b7sb1hw5qFeJhXm9H1nu3xSfLeQ==", "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/ini": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", - "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", - "dev": true, + "tslib": "^2.0.0" + }, "engines": { "node": ">=10" } }, - "node_modules/internal-slot": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", - "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "node_modules/aria-query": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", + "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", "dependencies": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" + "deep-equal": "^2.0.5" } }, - "node_modules/is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "node_modules/array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", "dependencies": { "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" + "is-array-buffer": "^3.0.1" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "dev": true + }, + "node_modules/array-includes": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", + "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", "dependencies": { "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "get-intrinsic": "^1.1.3", + "is-string": "^1.0.7" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dependencies": { - "has-bigints": "^1.0.1" + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-binary-path": { + "node_modules/array-union": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "devOptional": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, "engines": { "node": ">=8" } }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "node_modules/array.prototype.flat": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", + "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", "dependencies": { "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -6861,10 +8235,16 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "node_modules/array.prototype.flatmap": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", + "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0" + }, "engines": { "node": ">= 0.4" }, @@ -6872,151 +8252,165 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-ci": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", - "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", - "dev": true, + "node_modules/array.prototype.tosorted": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.1.tgz", + "integrity": "sha512-pZYPXPRl2PqWcsUs6LOMn+1f1532nEoPTYowBtqLwAW+W8vSVhkIGnmOX1t/UQjD6YGI0vcD2B1U7ZFGQH9jnQ==", "dependencies": { - "ci-info": "^3.2.0" - }, - "bin": { - "is-ci": "bin.js" + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0", + "get-intrinsic": "^1.1.3" } }, - "node_modules/is-core-module": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", - "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "dev": true + }, + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "dev": true, "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "safer-buffer": "~2.1.0" } }, - "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "node_modules/assert": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-2.1.0.tgz", + "integrity": "sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==", + "dev": true, "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "call-bind": "^1.0.2", + "is-nan": "^1.3.2", + "object-is": "^1.1.5", + "object.assign": "^4.1.4", + "util": "^0.12.5" } }, - "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "node_modules/assert-never": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/assert-never/-/assert-never-1.2.1.tgz", + "integrity": "sha512-TaTivMB6pYI1kXwrFlEhLeGfOqoDNdTxjCdwRfFFkEA30Eu+k48W34nlok2EYWJfFFzqaEmichdNM7th6M5HNw==", + "dev": true + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", "dev": true, - "bin": { - "is-docker": "cli.js" - }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.8" } }, - "node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dependencies": { - "is-plain-object": "^2.0.4" - }, + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, "engines": { - "node": ">=0.10.0" + "node": "*" } }, - "node_modules/is-extendable/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "node_modules/ast-types": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz", + "integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==", + "dev": true, "dependencies": { - "isobject": "^3.0.1" + "tslib": "^2.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "engines": { - "node": ">=0.10.0" - } + "node_modules/ast-types-flow": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", + "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==" }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", "dev": true, "engines": { "node": ">=8" } }, - "node_modules/is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "node_modules/async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", + "dev": true }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dependencies": { - "is-extglob": "^2.1.1" - }, + "node_modules/async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", + "dev": true + }, + "node_modules/async-validator": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-4.2.5.tgz", + "integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">= 4.0.0" } }, - "node_modules/is-installed-globally": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", - "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", + "node_modules/autoprefixer": { + "version": "10.4.14", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.14.tgz", + "integrity": "sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + } + ], "dependencies": { - "global-dirs": "^3.0.0", - "is-path-inside": "^3.0.2" + "browserslist": "^4.21.5", + "caniuse-lite": "^1.0.30001464", + "fraction.js": "^4.2.0", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.0", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" }, "engines": { - "node": ">=10" + "node": "^10 || ^12 || >=14" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", - "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "postcss": "^8.1.0" } }, - "node_modules/is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", "engines": { "node": ">= 0.4" }, @@ -7024,1267 +8418,1327 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "devOptional": true, + "node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", + "dev": true, "engines": { - "node": ">=0.12.0" + "node": "*" } }, - "node_modules/is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, + "node_modules/aws4": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", + "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==", + "dev": true + }, + "node_modules/axe-core": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.6.3.tgz", + "integrity": "sha512-/BQzOX780JhsxDnPpH4ZiyrJAzcd8AfzFPkv+89veFSr1rcMjuq2JDCwypKaPeB6ljHp9KjXhPpjgCvQlWYuqg==", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=4" } }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "engines": { - "node": ">=8" + "node_modules/axios": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.22.0.tgz", + "integrity": "sha512-Z0U3uhqQeg1oNcihswf4ZD57O3NrR1+ZXhxaROaWpDmsDTx7T2HNBV2ulBtie2hwJptu8UvgnJoK+BIqdzh/1w==", + "dependencies": { + "follow-redirects": "^1.14.4" } }, - "node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "node_modules/axobject-query": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz", + "integrity": "sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==", + "dependencies": { + "deep-equal": "^2.0.5" + } + }, + "node_modules/babel-core": { + "version": "7.0.0-bridge.0", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz", + "integrity": "sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==", + "dev": true, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-merge": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/babel-merge/-/babel-merge-3.0.0.tgz", + "integrity": "sha512-eBOBtHnzt9xvnjpYNI5HmaPp/b2vMveE5XggzqHnQeHJ8mFIBrBv6WZEVIj5jJ2uwTItkqKo9gWzEEcBxEq0yw==", + "dependencies": { + "deepmerge": "^2.2.1", + "object.omit": "^3.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-merge/node_modules/deepmerge": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz", + "integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==", "engines": { "node": ">=0.10.0" } }, - "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/is-set": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", - "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.8", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.8.tgz", + "integrity": "sha512-OtIuQfafSzpo/LhnJaykc0R/MMnuLSSVjVYy9mHArIZ9qTCSZ6TpWCuEKZYVoN//t8HqBNScHrOtCrIK5IaGLg==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.5.0", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.8.7", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.7.tgz", + "integrity": "sha512-KyDvZYxAzkC0Aj2dAPyDzi2Ym15e5JKZSK+maI7NAwSqofvuFglbSsxE7wUOvTg9oFVnHMzVzBKcqEb4PJgtOA==", + "dev": true, "dependencies": { - "call-bind": "^1.0.2" + "@babel/helper-define-polyfill-provider": "^0.4.4", + "core-js-compat": "^3.33.1" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, - "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "node_modules/babel-plugin-polyfill-corejs3/node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.4.tgz", + "integrity": "sha512-QcJMILQCu2jm5TFPGA3lCpJJTeEP+mqeXooG/NZbg/h5FTFi6V0+99ahlRsW8/kRLyb24LZVCCiclDedhLKcBA==", + "dev": true, "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, - "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.5.tgz", + "integrity": "sha512-OJGYZlhLqBh2DDHeqAxWB1XIvr49CxiJ2gIt61/PU55CQK4Z58OzMqjDe1zwQdQk+rBYsRc+1rJmdajM3gimHg==", + "dev": true, "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" + "@babel/helper-define-polyfill-provider": "^0.5.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, - "node_modules/is-typed-array": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", - "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "node_modules/babel-walk": { + "version": "3.0.0-canary-5", + "resolved": "https://registry.npmjs.org/babel-walk/-/babel-walk-3.0.0-canary-5.tgz", + "integrity": "sha512-GAwkz0AihzY5bkwIY5QDR+LvsRQgB/B+1foMPvi0FZPMl5fjD7ICiznUiBdLYMH1QYe6vqu4gWYytZOccLouFw==", + "dev": true, "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" + "@babel/types": "^7.9.6" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 10.0.0" } }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", - "dev": true + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, - "node_modules/is-weakmap": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", - "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "node_modules/batch-processor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/batch-processor/-/batch-processor-1.0.0.tgz", + "integrity": "sha512-xoLQD8gmmR32MeuBHgH0Tzd5PuSZx71ZsbhVxOCRbgktZEPe4SQy7s9Z50uPp0F/f7iw2XmkHN2xkgbMfckMDA==" }, - "node_modules/is-weakref": { + "node_modules/bcrypt-pbkdf": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "dev": true, "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "tweetnacl": "^0.14.3" } }, - "node_modules/is-weakset": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", - "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "node_modules/before-after-hook": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", + "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==" }, - "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "node_modules/better-opn": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/better-opn/-/better-opn-3.0.2.tgz", + "integrity": "sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ==", "dev": true, "dependencies": { - "is-docker": "^2.0.0" + "open": "^8.0.4" }, "engines": { - "node": ">=8" + "node": ">=12.0.0" } }, - "node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + "node_modules/big-integer": { + "version": "1.6.52", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", + "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", + "dev": true, + "engines": { + "node": ">=0.6" + } }, - "node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", "engines": { - "node": ">=0.10.0" + "node": "*" } }, - "node_modules/isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", - "dev": true + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "devOptional": true, + "engines": { + "node": ">=8" + } }, - "node_modules/jest-util": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.5.0.tgz", - "integrity": "sha512-RYMgG/MTadOr5t8KdhejfvUU82MxsCu5MF6KuDUHl+NuwzUt+Sm6jJWxTJVrDR1j5M/gJVCPKQEpWXY+yIQ6lQ==", + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", "dev": true, "dependencies": { - "@jest/types": "^29.5.0", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" } }, - "node_modules/jest-util/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/blob-util": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz", + "integrity": "sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==", + "dev": true + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "node_modules/body-parser": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" } }, - "node_modules/jest-util/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/body-parser/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">= 0.8" } }, - "node_modules/jest-util/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" + "ms": "2.0.0" } }, - "node_modules/jest-util/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-util/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==", + "node_modules/body-parser/node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "dev": true, "engines": { - "node": ">=8" + "node": ">= 0.8" } }, - "node_modules/jest-util/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/body-parser/node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" }, "engines": { - "node": ">=8" + "node": ">= 0.8" } }, - "node_modules/jest-worker": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.5.0.tgz", - "integrity": "sha512-NcrQnevGoSp4b5kg+akIpthoAFHxPBcb5P6mYPY0fUNT+sSvmtu6jlkEle3anczUKIKEbMxFimk9oTP/tpIPgA==", + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/body-parser/node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", "dev": true, "dependencies": { - "@types/node": "*", - "jest-util": "^29.5.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" + "side-channel": "^1.0.4" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-worker/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==", + "node_modules/body-parser/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", "dev": true, "engines": { - "node": ">=8" + "node": ">= 0.8" } }, - "node_modules/jest-worker/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==", + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" + }, + "node_modules/bplist-parser": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", + "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "big-integer": "^1.6.44" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "node": ">= 5.10.0" } }, - "node_modules/joi": { - "version": "17.9.1", - "resolved": "https://registry.npmjs.org/joi/-/joi-17.9.1.tgz", - "integrity": "sha512-FariIi9j6QODKATGBrEX7HZcja8Bsh3rfdGYy/Sb65sGlZWK/QWesU1ghk7aJWDj95knjXlQfSmzFSPPkLVsfw==", - "dev": true, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dependencies": { - "@hapi/hoek": "^9.0.0", - "@hapi/topo": "^5.0.0", - "@sideway/address": "^4.1.3", - "@sideway/formula": "^3.0.1", - "@sideway/pinpoint": "^2.0.0" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/js-sdsl": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.4.0.tgz", - "integrity": "sha512-FfVSdx6pJ41Oa+CF7RDaFmTnCaFhua+SNYQX74riGOpl96x+2jQCqEfQ2bnXu/5DPCqlRuiqyvTJM0Qjz26IVg==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/js-sdsl" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "devOptional": true, "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", - "dev": true - }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "bin": { - "jsesc": "bin/jsesc" + "fill-range": "^7.0.1" }, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "peer": true - }, - "node_modules/json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "node_modules/browser-assert": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/browser-assert/-/browser-assert-1.2.1.tgz", + "integrity": "sha512-nfulgvOR6S4gt9UKCeGJOuSGBPGiFT6oQ/2UBnvTY/5aQ1PnksW72fhZkM30DzoRRv2WpwZf1vHHEr3mtuXIWQ==", "dev": true }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" - }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "dev": true + "node_modules/browserify-zlib": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", + "integrity": "sha512-19OEpq7vWgsH6WkvkBJQDFvJS1uPcbFOQ4v9CU839dO+ZZXUZO6XpE6hNCqvlIIj+4fZvRiJ6DsAQ382GwiyTQ==", + "dev": true, + "dependencies": { + "pako": "~0.2.0" + } }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "node_modules/browserslist": { + "version": "4.22.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", + "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001565", + "electron-to-chromium": "^1.4.601", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" + }, "bin": { - "json5": "lib/cli.js" + "browserslist": "cli.js" }, "engines": { - "node": ">=6" + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/jsonc-parser": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", - "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", - "dev": true - }, - "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", "dev": true, "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "node-int64": "^0.4.0" } }, - "node_modules/jsprim": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz", - "integrity": "sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==", + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", "dev": true, - "engines": [ - "node >=0.6.0" + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } ], "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" } }, - "node_modules/jsx-ast-utils": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz", - "integrity": "sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==", - "dependencies": { - "array-includes": "^3.1.5", - "object.assign": "^4.1.3" - }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "dev": true, "engines": { - "node": ">=4.0" + "node": "*" } }, - "node_modules/keygrip": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz", - "integrity": "sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==", + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", "dev": true, - "dependencies": { - "tsscmp": "1.0.6" - }, "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, - "node_modules/koa": { - "version": "2.14.1", - "resolved": "https://registry.npmjs.org/koa/-/koa-2.14.1.tgz", - "integrity": "sha512-USJFyZgi2l0wDgqkfD27gL4YGno7TfUkcmOe6UOLFOVuN+J7FwnNu4Dydl4CUQzraM1lBAiGed0M9OVJoT0Kqw==", + "node_modules/cache-content-type": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-content-type/-/cache-content-type-1.0.1.tgz", + "integrity": "sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA==", "dev": true, "dependencies": { - "accepts": "^1.3.5", - "cache-content-type": "^1.0.0", - "content-disposition": "~0.5.2", - "content-type": "^1.0.4", - "cookies": "~0.8.0", - "debug": "^4.3.2", - "delegates": "^1.0.0", - "depd": "^2.0.0", - "destroy": "^1.0.4", - "encodeurl": "^1.0.2", - "escape-html": "^1.0.3", - "fresh": "~0.5.2", - "http-assert": "^1.3.0", - "http-errors": "^1.6.3", - "is-generator-function": "^1.0.7", - "koa-compose": "^4.1.0", - "koa-convert": "^2.0.0", - "on-finished": "^2.3.0", - "only": "~0.0.2", - "parseurl": "^1.3.2", - "statuses": "^1.5.0", - "type-is": "^1.6.16", - "vary": "^1.1.2" + "mime-types": "^2.1.18", + "ylru": "^1.2.0" }, "engines": { - "node": "^4.8.4 || ^6.10.1 || ^7.10.1 || >= 8.1.4" + "node": ">= 6.0.0" } }, - "node_modules/koa-compose": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-4.1.0.tgz", - "integrity": "sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw==", - "dev": true - }, - "node_modules/koa-convert": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/koa-convert/-/koa-convert-2.0.0.tgz", - "integrity": "sha512-asOvN6bFlSnxewce2e/DK3p4tltyfC4VM7ZwuTuepI7dEQVcvpyFuBcEARu1+Hxg8DIwytce2n7jrZtRlPrARA==", + "node_modules/cachedir": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.3.0.tgz", + "integrity": "sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw==", "dev": true, - "dependencies": { - "co": "^4.6.0", - "koa-compose": "^4.1.0" - }, "engines": { - "node": ">= 10" + "node": ">=6" } }, - "node_modules/koa-send": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/koa-send/-/koa-send-5.0.1.tgz", - "integrity": "sha512-tmcyQ/wXXuxpDxyNXv5yNNkdAMdFRqwtegBXUaowiQzUKqJehttS0x2j0eOZDQAyloAth5w6wwBImnFzkUz3pQ==", - "dev": true, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", "dependencies": { - "debug": "^4.1.1", - "http-errors": "^1.7.3", - "resolve-path": "^1.4.0" + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "engines": { - "node": ">= 8" + "node": ">=6" } }, - "node_modules/koa-static": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/koa-static/-/koa-static-5.0.0.tgz", - "integrity": "sha512-UqyYyH5YEXaJrf9S8E23GoJFQZXkBVJ9zYYMPGz919MSX1KuvAcycIuS0ci150HCoPf4XQVhQ84Qf8xRPWxFaQ==", + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true, - "dependencies": { - "debug": "^3.1.0", - "koa-send": "^5.0.0" - }, "engines": { - "node": ">= 7.6.0" + "node": ">=6" } }, - "node_modules/koa-static/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", "dev": true, - "dependencies": { - "ms": "^2.1.1" + "engines": { + "node": ">= 6" } }, - "node_modules/koa/node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "node_modules/caniuse-api": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", + "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", "dev": true, - "engines": { - "node": ">= 0.8" + "dependencies": { + "browserslist": "^4.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" } }, - "node_modules/language-subtag-registry": { - "version": "0.3.22", - "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", - "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==" + "node_modules/caniuse-lite": { + "version": "1.0.30001580", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001580.tgz", + "integrity": "sha512-mtj5ur2FFPZcCEpXFy8ADXbDACuNFXg6mxVDqp7tqooX6l3zwm+d8EPoeOSIFRDvHs8qu7/SLFOGniULkcH2iA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] }, - "node_modules/language-tags": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz", - "integrity": "sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==", - "dependencies": { - "language-subtag-registry": "~0.3.2" + "node_modules/case-anything": { + "version": "2.1.11", + "resolved": "https://registry.npmjs.org/case-anything/-/case-anything-2.1.11.tgz", + "integrity": "sha512-uzKDXzdM/x914cepWPzElU3y50NRKYhjkO4ittOHLq+rF6M0AgRLF/+yPR1tvwLNAh8WHEPTfhuciZGPfX+oyg==", + "engines": { + "node": ">=12.13" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" } }, - "node_modules/lazy-ass": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz", - "integrity": "sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw==", + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", + "dev": true + }, + "node_modules/chai": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz", + "integrity": "sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==", "dev": true, + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.3", + "deep-eql": "^4.1.3", + "get-func-name": "^2.0.2", + "loupe": "^2.3.6", + "pathval": "^1.1.1", + "type-detect": "^4.0.8" + }, "engines": { - "node": "> 0.8" + "node": ">=4" } }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">=4" } }, - "node_modules/lilconfig": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", - "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "node_modules/character-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/character-parser/-/character-parser-2.2.0.tgz", + "integrity": "sha512-+UqJQjFEFaTAs3bNsF2j2kEN1baG/zghZbdqoYEDxGZtJo9LBzl1A+m0D4n3qKx8N2FNv8/Xp6yV9mQmBuptaw==", "dev": true, - "engines": { - "node": ">=10" + "dependencies": { + "is-regex": "^1.0.3" } }, - "node_modules/linkify-it": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-4.0.1.tgz", - "integrity": "sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==", - "dependencies": { - "uc.micro": "^1.0.1" + "node_modules/chart.js": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.9.1.tgz", + "integrity": "sha512-Ro2JbLmvg83gXF5F4sniaQ+lTbSv18E+TIf2cOeiH1Iqd2PGFOtem+DUufMZsCJwFE7ywPOpfXFBwRTGq7dh6w==" + }, + "node_modules/chartjs-adapter-date-fns": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chartjs-adapter-date-fns/-/chartjs-adapter-date-fns-3.0.0.tgz", + "integrity": "sha512-Rs3iEB3Q5pJ973J93OBTpnP7qoGwvq3nUnoMdtxO+9aoJof7UFcRbWcIDteXuYd1fgAvct/32T9qaLyLuZVwCg==", + "optional": true, + "peerDependencies": { + "chart.js": ">=2.8.0", + "date-fns": ">=2.0.0" } }, - "node_modules/linkifyjs": { + "node_modules/chartjs-adapter-moment": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/chartjs-adapter-moment/-/chartjs-adapter-moment-1.0.1.tgz", + "integrity": "sha512-Uz+nTX/GxocuqXpGylxK19YG4R3OSVf8326D+HwSTsNw1LgzyIGRo+Qujwro1wy6X+soNSnfj5t2vZ+r6EaDmA==", + "peerDependencies": { + "chart.js": ">=3.0.0", + "moment": "^2.10.2" + } + }, + "node_modules/chartjs-plugin-annotation": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/chartjs-plugin-annotation/-/chartjs-plugin-annotation-2.2.1.tgz", + "integrity": "sha512-RL9UtrFr2SXd7C47zD0MZqn6ZLgrcRt3ySC6cYal2amBdANcYB1QcwFXcpKWAYnO4SGJYRok7P5rKDDNgJMA/w==", + "peerDependencies": { + "chart.js": ">=3.7.0" + } + }, + "node_modules/chartkick": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/linkifyjs/-/linkifyjs-4.1.1.tgz", - "integrity": "sha512-zFN/CTVmbcVef+WaDXT63dNzzkfRBKT1j464NJQkV7iSgJU0sLBus9W0HBwnXK13/hf168pbrx/V/bjEHOXNHA==" + "resolved": "git+ssh://git@github.com/CrowdDotDev/chartkick.js.git#622a0fa30efebe1ff7380e4182536cc2816c8da5", + "license": "MIT", + "optionalDependencies": { + "chart.js": ">=3.0.2", + "chartjs-adapter-date-fns": ">=2.0.0", + "date-fns": ">=2.0.0" + } }, - "node_modules/listr2": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.14.0.tgz", - "integrity": "sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g==", + "node_modules/check-error": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", + "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", "dev": true, "dependencies": { - "cli-truncate": "^2.1.0", - "colorette": "^2.0.16", - "log-update": "^4.0.0", - "p-map": "^4.0.0", - "rfdc": "^1.3.0", - "rxjs": "^7.5.1", - "through": "^2.3.8", - "wrap-ansi": "^7.0.0" + "get-func-name": "^2.0.2" }, "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "enquirer": ">= 2.3.0 < 3" - }, - "peerDependenciesMeta": { - "enquirer": { - "optional": true - } + "node": "*" } }, - "node_modules/loader-runner": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", - "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", - "peer": true, + "node_modules/check-more-types": { + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", + "integrity": "sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==", + "dev": true, "engines": { - "node": ">=6.11.5" + "node": ">= 0.8.0" } }, - "node_modules/local-pkg": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.4.3.tgz", - "integrity": "sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==", - "dev": true, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "devOptional": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, "engines": { - "node": ">=14" + "node": ">= 8.10.0" }, - "funding": { - "url": "https://github.com/sponsors/antfu" + "optionalDependencies": { + "fsevents": "~2.3.2" } }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "devOptional": true, "dependencies": { - "p-locate": "^5.0.0" + "is-glob": "^4.0.1" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 6" } }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "node_modules/lodash-es": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", - "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" - }, - "node_modules/lodash-unified": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/lodash-unified/-/lodash-unified-1.0.3.tgz", - "integrity": "sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ==", - "peerDependencies": { - "@types/lodash-es": "*", - "lodash": "*", - "lodash-es": "*" + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true, + "engines": { + "node": ">=10" } }, - "node_modules/lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", - "dev": true + "node_modules/chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "peer": true, + "engines": { + "node": ">=6.0" + } }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" + "node_modules/ci-info": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", + "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } }, - "node_modules/lodash.once": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", - "dev": true + "node_modules/citty": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.5.tgz", + "integrity": "sha512-AS7n5NSc0OQVMV9v6wt3ByujNIrne0/cTjiC2MYqhvao57VNfiuVksTSr2p17nVOhEr2KtqiAkGwHcgMC/qUuQ==", + "dev": true, + "dependencies": { + "consola": "^3.2.3" + } }, - "node_modules/lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", - "dev": true + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true, + "engines": { + "node": ">=6" + } }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", "dev": true, "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" + "restore-cursor": "^3.1.0" }, "engines": { - "node": ">=10" + "node": ">=8" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "dev": true, + "engines": { + "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/log-symbols/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/cli-table3": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz", + "integrity": "sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "string-width": "^4.2.0" }, "engines": { - "node": ">=8" + "node": "10.* || >= 12.*" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "optionalDependencies": { + "@colors/colors": "1.5.0" } }, - "node_modules/log-symbols/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/cli-truncate": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", + "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "slice-ansi": "^3.0.0", + "string-width": "^4.2.0" }, "engines": { - "node": ">=10" + "node": ">=8" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/log-symbols/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, "dependencies": { - "color-name": "~1.1.4" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" }, "engines": { - "node": ">=7.0.0" + "node": ">=12" } }, - "node_modules/log-symbols/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/log-symbols/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==", + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", "dev": true, "engines": { - "node": ">=8" + "node": ">=0.8" } }, - "node_modules/log-symbols/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" }, "engines": { - "node": ">=8" + "node": ">=6" } }, - "node_modules/log-update": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", - "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", + "node_modules/clone-deep/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "dev": true, "dependencies": { - "ansi-escapes": "^4.3.0", - "cli-cursor": "^3.1.0", - "slice-ansi": "^4.0.0", - "wrap-ansi": "^6.2.0" + "isobject": "^3.0.1" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, - "node_modules/log-update/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" } }, - "node_modules/log-update/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/colord": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", + "dev": true + }, + "node_modules/colorette": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz", + "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==", + "dev": true + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "dev": true, "dependencies": { - "color-name": "~1.1.4" + "delayed-stream": "~1.0.0" }, "engines": { - "node": ">=7.0.0" + "node": ">= 0.8" } }, - "node_modules/log-update/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "node_modules/commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/common-tags": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", + "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", "dev": true }, - "node_modules/log-update/node_modules/slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", "dev": true, "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" + "mime-db": ">= 1.43.0 < 2" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" + "node": ">= 0.6" } }, - "node_modules/log-update/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "node_modules/compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", "dev": true, "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" }, "engines": { - "node": ">=8" + "node": ">= 0.8.0" } }, - "node_modules/logrocket": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/logrocket/-/logrocket-3.0.1.tgz", - "integrity": "sha512-jOWG+jEzobKVxGytzZ+4KGm2kiMQMRTHab2uDWQyVZcHfEF38BlCH1yjQVY4LCmuQUwZitP9biMzJZnyUQ0dtQ==" - }, - "node_modules/logrocket-vuex": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/logrocket-vuex/-/logrocket-vuex-0.0.3.tgz", - "integrity": "sha512-Xnl3pBEkc/bbtZ5JEtFwqNjVuLzVEohlBpyQHP47BlO+/6sFmSM2JcNWojysYUo4cp3IWpmWXcezax2+Cq4RsA==" - }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" + "ms": "2.0.0" } }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dependencies": { - "yallist": "^3.0.2" - } + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true }, - "node_modules/magic-string": { - "version": "0.30.0", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.0.tgz", - "integrity": "sha512-LA+31JYDJLs82r2ScLrlz1GjSgu66ZV518eyWT+S8VhyQn/JL0u9MeBOvQMGYiPk1DBiSN9DDMOcXvigJZaViQ==", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.4.13" - }, - "engines": { - "node": ">=12" - } + "node_modules/compression/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, - "node_modules/markdown-it": { - "version": "13.0.1", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-13.0.1.tgz", - "integrity": "sha512-lTlxriVoy2criHP0JKRhO2VDG9c2ypWCsT237eDiLqi09rmbKoUetyGHq2uOIRoRS//kfoJckS0eUzzkDR+k2Q==", + "node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "engines": [ + "node >= 0.8" + ], "dependencies": { - "argparse": "^2.0.1", - "entities": "~3.0.1", - "linkify-it": "^4.0.1", - "mdurl": "^1.0.1", - "uc.micro": "^1.0.5" - }, - "bin": { - "markdown-it": "bin/markdown-it.js" - } - }, - "node_modules/marked": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", - "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", - "bin": { - "marked": "bin/marked.js" - }, - "engines": { - "node": ">= 12" + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" } }, - "node_modules/mdn-data": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", - "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", + "node_modules/concat-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", "dev": true }, - "node_modules/mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==" - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, - "engines": { - "node": ">= 0.6" + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, - "node_modules/memoize-one": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", - "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==" + "node_modules/concat-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + "node_modules/concat-stream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "node_modules/concurrently": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-7.6.0.tgz", + "integrity": "sha512-BKtRgvcJGeZ4XttiDiNcFiRlxoAeZOseqUvyYRUp/Vtd+9p1ULmeoSqGsDA+2ivdeDFpqrJvGvmI+StKfKl5hw==", "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "date-fns": "^2.29.1", + "lodash": "^4.17.21", + "rxjs": "^7.0.0", + "shell-quote": "^1.7.3", + "spawn-command": "^0.0.2-1", + "supports-color": "^8.1.0", + "tree-kill": "^1.2.2", + "yargs": "^17.3.1" + }, + "bin": { + "conc": "dist/bin/concurrently.js", + "concurrently": "dist/bin/concurrently.js" + }, "engines": { - "node": ">= 8" + "node": "^12.20.0 || ^14.13.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" } }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "node_modules/concurrently/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">= 0.6" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "node_modules/concurrently/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=8.6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "node_modules/concurrently/node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { - "node": ">= 0.6" + "node": ">=8" } }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "node_modules/concurrently/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { - "mime-db": "1.52.0" + "color-name": "~1.1.4" }, "engines": { - "node": ">= 0.6" + "node": ">=7.0.0" } }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "node_modules/concurrently/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/concurrently/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": ">=6" + "node": ">=8" } }, - "node_modules/mini-css-extract-plugin": { - "version": "2.7.5", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.5.tgz", - "integrity": "sha512-9HaR++0mlgom81s95vvNjxkg52n2b5s//3ZTI1EtzFb98awsLSivs2LMsVqnQ3ay0PVhqWcGNyDaTE961FOcjQ==", + "node_modules/concurrently/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": { - "schema-utils": "^4.0.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">= 12.13.0" + "node": ">=10" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/mini-css-extract-plugin/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "node_modules/confusing-browser-globals": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", + "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==" + }, + "node_modules/consola": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.2.3.tgz", + "integrity": "sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==", "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "engines": { + "node": "^14.18.0 || >=16.10.0" } }, - "node_modules/mini-css-extract-plugin/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "node_modules/constantinople": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-4.0.1.tgz", + "integrity": "sha512-vCrqcSIq4//Gx74TXXCGnHpulY1dskqLTFGDmhrGxzeXL8lF8kvXv6mpNWlJj1uD4DW23D4ljAqbY4RRaaUZIw==", "dev": true, "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" + "@babel/parser": "^7.6.0", + "@babel/types": "^7.6.1" } }, - "node_modules/mini-css-extract-plugin/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "node_modules/mini-css-extract-plugin/node_modules/schema-utils": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", - "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", "dev": true, "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.8.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.0.0" + "safe-buffer": "5.2.1" }, "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "node": ">= 0.6" } }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "dev": true, "engines": { - "node": "*" + "node": ">= 0.6" } }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" + }, + "node_modules/cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "dev": true, + "engines": { + "node": ">= 0.6" } }, - "node_modules/mitt": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.0.tgz", - "integrity": "sha512-7dX2/10ITVyqh4aOSVI9gdape+t9l2/8QxHrFmUXu4EEUpdlxl6RudZUPZoc+zuY2hk1j7XxVroIVIan/pD/SQ==" + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "dev": true }, - "node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "node_modules/cookies": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/cookies/-/cookies-0.8.0.tgz", + "integrity": "sha512-8aPsApQfebXnuI+537McwYsDtjVxGm8gTIzQI3FDW6t5t/DAhERxtnbEPN/8RX+uZthoz4eCOgloXaE5cYyNow==", "dev": true, "dependencies": { - "minimist": "^1.2.6" + "depd": "~2.0.0", + "keygrip": "~1.1.0" }, - "bin": { - "mkdirp": "bin/cmd.js" + "engines": { + "node": ">= 0.8" } }, - "node_modules/mlly": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.2.0.tgz", - "integrity": "sha512-+c7A3CV0KGdKcylsI6khWyts/CYrGTrRVo4R/I7u/cUsy0Conxa6LUhiEzVKIw14lc2L5aiO4+SeVe4TeGRKww==", + "node_modules/cookies/node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "dev": true, - "dependencies": { - "acorn": "^8.8.2", - "pathe": "^1.1.0", - "pkg-types": "^1.0.2", - "ufo": "^1.1.1" - } - }, - "node_modules/moment": { - "version": "2.29.4", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", - "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", "engines": { - "node": "*" + "node": ">= 0.8" } }, - "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==" - }, - "node_modules/nanoclone": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/nanoclone/-/nanoclone-0.2.1.tgz", - "integrity": "sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA==" + "node_modules/core-js": { + "version": "3.24.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.24.1.tgz", + "integrity": "sha512-0QTBSYSUZ6Gq21utGzkfITDylE8jWC9Ne1D2MrhvlsZBI1x39OdDIVbzSqtgMndIy6BlHxBXpMGqzZmnztg2rg==", + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } }, - "node_modules/nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "bin": { - "nanoid": "bin/nanoid.cjs" + "node_modules/core-js-compat": { + "version": "3.35.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.35.1.tgz", + "integrity": "sha512-sftHa5qUJY3rs9Zht1WEnmkvXputCyDBczPnr7QDgL8n3qrF3CMXY4VPSYtOLLiOUJcah2WNXREd48iOl6mQIw==", + "dev": true, + "dependencies": { + "browserslist": "^4.22.2" }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" } }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" - }, - "node_modules/natural-compare-lite": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", - "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", "dev": true }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "peer": true + "node_modules/crelt": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.5.tgz", + "integrity": "sha512-+BO9wPPi+DWTDcNYhr/W90myha8ptzftZT+LwcmUbbok0rcP/fequmFYCw8NMoH7pkAZQzU78b3kYrlua5a9eA==" }, - "node_modules/node-emoji": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", - "integrity": "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==", + "node_modules/cross-fetch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", + "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", "dependencies": { - "lodash": "^4.17.21" + "node-fetch": "2.6.7" } }, - "node_modules/node-fetch": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz", - "integrity": "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==", + "node_modules/cross-fetch/node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", "dependencies": { "whatwg-url": "^5.0.0" }, @@ -8300,1564 +9754,1690 @@ } } }, - "node_modules/node-releases": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", - "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==" - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "devOptional": true, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 8" } }, - "node_modules/normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "node_modules/crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/normalize-url": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "node_modules/css-declaration-sorter": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.4.0.tgz", + "integrity": "sha512-jDfsatwWMWN0MODAFuHszfjphEXfNw9JUAhmY4pLu3TyTU+ohUpsbVtbU+1MZn4a47D9kqh03i4eyOm+74+zew==", "dev": true, "engines": { - "node": ">=10" + "node": "^10 || ^12 || >=14" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "postcss": "^8.0.9" } }, - "node_modules/normalize-wheel-es": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/normalize-wheel-es/-/normalize-wheel-es-1.2.0.tgz", - "integrity": "sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw==" - }, - "node_modules/nprogress": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz", - "integrity": "sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==" - }, - "node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "node_modules/css-minimizer-webpack-plugin": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-4.2.2.tgz", + "integrity": "sha512-s3Of/4jKfw1Hj9CxEO1E5oXhQAxlayuHO2y/ML+C6I9sQ7FdzfEV6QgMLN3vI+qFsjJGIAFLKtQK7t8BOXAIyA==", + "dev": true, "dependencies": { - "boolbase": "^1.0.0" + "cssnano": "^5.1.8", + "jest-worker": "^29.1.2", + "postcss": "^8.4.17", + "schema-utils": "^4.0.0", + "serialize-javascript": "^6.0.0", + "source-map": "^0.6.1" }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-hash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", - "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "node": ">= 14.15.0" + }, "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-is": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", - "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "type": "opencollective", + "url": "https://opencollective.com/webpack" }, - "engines": { - "node": ">= 0.4" + "peerDependencies": { + "webpack": "^5.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "engines": { - "node": ">= 0.4" + "peerDependenciesMeta": { + "@parcel/css": { + "optional": true + }, + "@swc/css": { + "optional": true + }, + "clean-css": { + "optional": true + }, + "csso": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "lightningcss": { + "optional": true + } } }, - "node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "node_modules/css-minimizer-webpack-plugin/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/object.entries": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.6.tgz", - "integrity": "sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w==", + "node_modules/css-minimizer-webpack-plugin/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "fast-deep-equal": "^3.1.3" }, - "engines": { - "node": ">= 0.4" + "peerDependencies": { + "ajv": "^8.8.2" } }, - "node_modules/object.fromentries": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.6.tgz", - "integrity": "sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==", + "node_modules/css-minimizer-webpack-plugin/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/css-minimizer-webpack-plugin/node_modules/schema-utils": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", + "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", + "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "@types/json-schema": "^7.0.9", + "ajv": "^8.8.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">= 12.13.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, - "node_modules/object.hasown": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.2.tgz", - "integrity": "sha512-B5UIT3J1W+WuWIU55h0mjlwaqxiE5vYENJXIXZ4VFe05pNYrkKuK0U/6aFcb0pKywYJh7IhfoqUfKVmrJJHZHw==", + "node_modules/css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "dev": true, "dependencies": { - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" }, "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.omit": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-3.0.0.tgz", - "integrity": "sha512-EO+BCv6LJfu+gBIF3ggLicFebFLN5zqzz/WWJlMFfkMyGth+oBkhxzDl0wx2W4GkLzuQs/FsSkXZb2IMWQqmBQ==", - "dependencies": { - "is-extendable": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" + "url": "https://github.com/sponsors/fb55" } }, - "node_modules/object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==", + "node_modules/css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "dev": true, "dependencies": { - "isobject": "^3.0.1" + "mdn-data": "2.0.14", + "source-map": "^0.6.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=8.0.0" } }, - "node_modules/object.values": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", - "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "dev": true, "engines": { - "node": ">= 0.4" + "node": ">= 6" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/fb55" } }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dev": true, - "dependencies": { - "ee-first": "1.1.1" + "node_modules/css.escape": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", + "dev": true + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "bin": { + "cssesc": "bin/cssesc" }, "engines": { - "node": ">= 0.8" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dependencies": { - "wrappy": "1" + "node": ">=4" } }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "node_modules/cssnano": { + "version": "5.1.15", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.15.tgz", + "integrity": "sha512-j+BKgDcLDQA+eDifLx0EO4XSA56b7uut3BQFH+wbSaSTuGLuiyTa/wbRYthUXX8LC9mLg+WWKe8h+qJuwTAbHw==", "dev": true, "dependencies": { - "mimic-fn": "^2.1.0" + "cssnano-preset-default": "^5.2.14", + "lilconfig": "^2.0.3", + "yaml": "^1.10.2" }, "engines": { - "node": ">=6" + "node": "^10 || ^12 || >=14.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/cssnano" + }, + "peerDependencies": { + "postcss": "^8.2.15" } }, - "node_modules/only": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/only/-/only-0.0.2.tgz", - "integrity": "sha512-Fvw+Jemq5fjjyWz6CpKx6w9s7xxqo3+JCyM0WXWeCSOboZ8ABkyvP8ID4CZuChA/wxSx+XSJmdOm8rGVyJ1hdQ==", - "dev": true - }, - "node_modules/open": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", - "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "node_modules/cssnano-preset-default": { + "version": "5.2.14", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.2.14.tgz", + "integrity": "sha512-t0SFesj/ZV2OTylqQVOrFgEh5uanxbO6ZAdeCrNsUQ6fVuXwYTxJPNAGvGTxHbD68ldIJNec7PyYZDBrfDQ+6A==", "dev": true, "dependencies": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "css-declaration-sorter": "^6.3.1", + "cssnano-utils": "^3.1.0", + "postcss-calc": "^8.2.3", + "postcss-colormin": "^5.3.1", + "postcss-convert-values": "^5.1.3", + "postcss-discard-comments": "^5.1.2", + "postcss-discard-duplicates": "^5.1.0", + "postcss-discard-empty": "^5.1.1", + "postcss-discard-overridden": "^5.1.0", + "postcss-merge-longhand": "^5.1.7", + "postcss-merge-rules": "^5.1.4", + "postcss-minify-font-values": "^5.1.0", + "postcss-minify-gradients": "^5.1.1", + "postcss-minify-params": "^5.1.4", + "postcss-minify-selectors": "^5.2.1", + "postcss-normalize-charset": "^5.1.0", + "postcss-normalize-display-values": "^5.1.0", + "postcss-normalize-positions": "^5.1.1", + "postcss-normalize-repeat-style": "^5.1.1", + "postcss-normalize-string": "^5.1.0", + "postcss-normalize-timing-functions": "^5.1.0", + "postcss-normalize-unicode": "^5.1.1", + "postcss-normalize-url": "^5.1.0", + "postcss-normalize-whitespace": "^5.1.1", + "postcss-ordered-values": "^5.1.3", + "postcss-reduce-initial": "^5.1.2", + "postcss-reduce-transforms": "^5.1.0", + "postcss-svgo": "^5.1.0", + "postcss-unique-selectors": "^5.1.1" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" } }, - "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "node_modules/cssnano-utils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.1.0.tgz", + "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/csso": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", + "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", + "dev": true, "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" + "css-tree": "^1.1.2" }, "engines": { - "node": ">= 0.8.0" + "node": ">=8.0.0" } }, - "node_modules/orderedmap": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/orderedmap/-/orderedmap-2.1.0.tgz", - "integrity": "sha512-/pIFexOm6S70EPdznemIz3BQZoJ4VTFrhqzu0ACBqBgeLsLxq8e6Jim63ImIfwW/zAD1AlXpRMlOv3aghmo4dA==" - }, - "node_modules/ospath": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/ospath/-/ospath-1.2.2.tgz", - "integrity": "sha512-o6E5qJV5zkAbIDNhGSIlyOhScKXgQrSRMilfph0clDfM0nEnBOlKlH4sWDmG95BW/CvwNz0vmm7dJVtU2KlMiA==", - "dev": true + "node_modules/csstype": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", + "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "node_modules/cypress": { + "version": "10.11.0", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-10.11.0.tgz", + "integrity": "sha512-lsaE7dprw5DoXM00skni6W5ElVVLGAdRUUdZjX2dYsGjbY/QnpzWZ95Zom1mkGg0hAaO/QVTZoFVS7Jgr/GUPA==", + "dev": true, + "hasInstallScript": true, "dependencies": { - "yocto-queue": "^0.1.0" + "@cypress/request": "^2.88.10", + "@cypress/xvfb": "^1.2.4", + "@types/node": "^14.14.31", + "@types/sinonjs__fake-timers": "8.1.1", + "@types/sizzle": "^2.3.2", + "arch": "^2.2.0", + "blob-util": "^2.0.2", + "bluebird": "^3.7.2", + "buffer": "^5.6.0", + "cachedir": "^2.3.0", + "chalk": "^4.1.0", + "check-more-types": "^2.24.0", + "cli-cursor": "^3.1.0", + "cli-table3": "~0.6.1", + "commander": "^5.1.0", + "common-tags": "^1.8.0", + "dayjs": "^1.10.4", + "debug": "^4.3.2", + "enquirer": "^2.3.6", + "eventemitter2": "6.4.7", + "execa": "4.1.0", + "executable": "^4.1.1", + "extract-zip": "2.0.1", + "figures": "^3.2.0", + "fs-extra": "^9.1.0", + "getos": "^3.2.1", + "is-ci": "^3.0.0", + "is-installed-globally": "~0.4.0", + "lazy-ass": "^1.6.0", + "listr2": "^3.8.3", + "lodash": "^4.17.21", + "log-symbols": "^4.0.0", + "minimist": "^1.2.6", + "ospath": "^1.2.2", + "pretty-bytes": "^5.6.0", + "proxy-from-env": "1.0.0", + "request-progress": "^3.0.0", + "semver": "^7.3.2", + "supports-color": "^8.1.1", + "tmp": "~0.2.1", + "untildify": "^4.0.0", + "yauzl": "^2.10.0" + }, + "bin": { + "cypress": "bin/cypress" }, "engines": { - "node": ">=10" + "node": ">=12.0.0" + } + }, + "node_modules/cypress-mailosaur": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/cypress-mailosaur/-/cypress-mailosaur-2.13.0.tgz", + "integrity": "sha512-xdv2994VkGH79Ag+OY2V1Tkr9Uy9p5wE+3u+SB6nnJEvEDIT5cVPsxVJxr91THwR34NWoS3zQBt5ai5ZVZ/1/w==", + "dev": true, + "engines": { + "node": ">= v10.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "cypress": ">= 2.1.0" } }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "node_modules/cypress/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { - "p-limit": "^3.0.2" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=10" + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "node_modules/cypress/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "dependencies": { - "aggregate-error": "^3.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/papaparse": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/papaparse/-/papaparse-5.4.1.tgz", - "integrity": "sha512-HipMsgJkZu8br23pW15uvo6sib6wne/4woLZPlFf3rpDyMe9ywEXUsuD7+6K9PRkJlVT51j/sCOYDKGGS3ZJrw==" + "node_modules/cypress/node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "node_modules/cypress/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { - "callsites": "^3.0.0" + "color-name": "~1.1.4" }, "engines": { - "node": ">=6" + "node": ">=7.0.0" } }, - "node_modules/parse-srcset": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-srcset/-/parse-srcset-1.0.2.tgz", - "integrity": "sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q==" + "node_modules/cypress/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "node_modules/cypress/node_modules/execa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + }, "engines": { - "node": ">= 0.8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "node_modules/cypress/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "node_modules/cypress/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": ">=0.10.0" + "node": ">=8" } }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "node_modules/cypress/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" - }, - "node_modules/path-to-regexp": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz", - "integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==", - "dev": true - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "node_modules/cypress/node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/pathe": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.0.tgz", - "integrity": "sha512-ODbEPR0KKHqECXW1GoxdDb+AZvULmXjVPy4rt+pGo2+TnjJTIPJQSVS6N63n8T2Ip+syHhbn52OewKicV0373w==", - "dev": true - }, - "node_modules/pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", - "dev": true - }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", - "dev": true - }, - "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "devOptional": true, + "node_modules/cypress/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": ">=8.6" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true, + "node_modules/cypress/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/d3-dispatch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", + "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", + "peer": true, "engines": { - "node": ">=0.10.0" + "node": ">=12" } }, - "node_modules/pinia": { - "version": "2.0.33", - "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.0.33.tgz", - "integrity": "sha512-HOj1yVV2itw6rNIrR2f7+MirGNxhORjrULL8GWgRwXsGSvEqIQ+SE0MYt6cwtpegzCda3i+rVTZM+AM7CG+kRg==", + "node_modules/d3-force": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", + "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", + "peer": true, "dependencies": { - "@vue/devtools-api": "^6.5.0", - "vue-demi": "*" - }, - "funding": { - "url": "https://github.com/sponsors/posva" - }, - "peerDependencies": { - "@vue/composition-api": "^1.4.0", - "typescript": ">=4.4.4", - "vue": "^2.6.14 || ^3.2.0" + "d3-dispatch": "1 - 3", + "d3-quadtree": "1 - 3", + "d3-timer": "1 - 3" }, - "peerDependenciesMeta": { - "@vue/composition-api": { - "optional": true - }, - "typescript": { - "optional": true - } + "engines": { + "node": ">=12" } }, - "node_modules/pinia/node_modules/vue-demi": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.11.tgz", - "integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==", - "hasInstallScript": true, - "bin": { - "vue-demi-fix": "bin/vue-demi-fix.js", - "vue-demi-switch": "bin/vue-demi-switch.js" - }, + "node_modules/d3-quadtree": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", + "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", + "peer": true, "engines": { "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - }, - "peerDependencies": { - "@vue/composition-api": "^1.0.0-rc.1", - "vue": "^3.0.0-0 || ^2.6.0" - }, - "peerDependenciesMeta": { - "@vue/composition-api": { - "optional": true - } } }, - "node_modules/pkg-types": { + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==" + }, + "node_modules/dash-get": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.0.2.tgz", - "integrity": "sha512-hM58GKXOcj8WTqUXnsQyJYXdeAPbythQgEF3nTcEo+nkD49chjQ9IKm/QJy9xf6JakXptz86h7ecP2024rrLaQ==", + "resolved": "https://registry.npmjs.org/dash-get/-/dash-get-1.0.2.tgz", + "integrity": "sha512-4FbVrHDwfOASx7uQVxeiCTo7ggSdYZbqs8lH+WU6ViypPlDbe9y6IP5VVUDQBv9DcnyaiPT5XT0UWHgJ64zLeQ==" + }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", "dev": true, "dependencies": { - "jsonc-parser": "^3.2.0", - "mlly": "^1.1.1", - "pathe": "^1.1.0" + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" } }, - "node_modules/pluralize": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", - "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "node_modules/date-fns": { + "version": "2.29.3", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz", + "integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==", + "devOptional": true, "engines": { - "node": ">=4" + "node": ">=0.11" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/date-fns" } }, - "node_modules/portfinder": { - "version": "1.0.32", - "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.32.tgz", - "integrity": "sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg==", - "dev": true, + "node_modules/dayjs": { + "version": "1.11.7", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.7.tgz", + "integrity": "sha512-+Yw9U6YO5TQohxLcIkrXBeY73WP3ejHWVvx8XCk3gxvQDCTEmS48ZrSZCKciI7Bhl/uCMyxYtE9UqRILmFphkQ==" + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dependencies": { - "async": "^2.6.4", - "debug": "^3.2.7", - "mkdirp": "^0.5.6" + "ms": "2.1.2" }, "engines": { - "node": ">= 0.12.0" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/portfinder/node_modules/async": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", - "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "node_modules/deep-eql": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", + "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", "dev": true, "dependencies": { - "lodash": "^4.17.14" + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=6" } }, - "node_modules/portfinder/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, + "node_modules/deep-equal": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.0.tgz", + "integrity": "sha512-RdpzE0Hv4lhowpIUKKMJfeH6C1pXdtT1/it80ubgWqwI3qpuxUBpC1S4hnHg+zjnuOoDkzUtUCEEkG+XG5l3Mw==", "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/postcss": { - "version": "8.4.27", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.27.tgz", - "integrity": "sha512-gY/ACJtJPSmUFPDCHtX78+01fHa64FaU4zaaWfuh1MhGJISufJAH4cun6k/8fwsHYeK4UQmENQK+tRLCFJE8JQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], + "call-bind": "^1.0.2", + "es-get-iterator": "^1.1.2", + "get-intrinsic": "^1.1.3", + "is-arguments": "^1.1.1", + "is-array-buffer": "^3.0.1", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "isarray": "^2.0.5", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.4.3", + "side-channel": "^1.0.4", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/default-browser-id": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz", + "integrity": "sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==", + "dev": true, "dependencies": { - "nanoid": "^3.3.6", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" + "bplist-parser": "^0.2.0", + "untildify": "^4.0.0" }, "engines": { - "node": "^10 || ^12 || >=14" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/postcss-calc": { - "version": "8.2.4", - "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.4.tgz", - "integrity": "sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==", + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", "dev": true, "dependencies": { - "postcss-selector-parser": "^6.0.9", - "postcss-value-parser": "^4.2.0" + "clone": "^1.0.2" }, - "peerDependencies": { - "postcss": "^8.2.2" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/postcss-colormin": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.3.1.tgz", - "integrity": "sha512-UsWQG0AqTFQmpBegeLLc1+c3jIqBNB0zlDGRWR+dQ3pRKJL1oeMzyqmH3o2PIfn9MBdNrVPWhDbT769LxCTLJQ==", + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/define-properties": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", + "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", "dependencies": { - "browserslist": "^4.21.4", - "caniuse-api": "^3.0.0", - "colord": "^2.9.1", - "postcss-value-parser": "^4.2.0" + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" }, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": ">= 0.4" }, - "peerDependencies": { - "postcss": "^8.2.15" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/postcss-convert-values": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.1.3.tgz", - "integrity": "sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA==", + "node_modules/defined": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.1.tgz", + "integrity": "sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/defu": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", + "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", + "dev": true + }, + "node_modules/del": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/del/-/del-6.1.1.tgz", + "integrity": "sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==", "dev": true, "dependencies": { - "browserslist": "^4.21.4", - "postcss-value-parser": "^4.2.0" + "globby": "^11.0.1", + "graceful-fs": "^4.2.4", + "is-glob": "^4.0.1", + "is-path-cwd": "^2.2.0", + "is-path-inside": "^3.0.2", + "p-map": "^4.0.0", + "rimraf": "^3.0.2", + "slash": "^3.0.0" }, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": ">=10" }, - "peerDependencies": { - "postcss": "^8.2.15" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/postcss-discard-comments": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz", - "integrity": "sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==", + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "dev": true, "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node": ">=0.4.0" } }, - "node_modules/postcss-discard-duplicates": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz", - "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==", + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "dev": true + }, + "node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", "dev": true, "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node": ">= 0.6" } }, - "node_modules/postcss-discard-empty": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz", - "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==", + "node_modules/deprecation": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", "dev": true, "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node": ">=6" } }, - "node_modules/postcss-discard-overridden": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz", - "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==", + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", "dev": true, "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" } }, - "node_modules/postcss-import": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-14.1.0.tgz", - "integrity": "sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw==", + "node_modules/detect-indent": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", + "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", "dev": true, - "dependencies": { - "postcss-value-parser": "^4.0.0", - "read-cache": "^1.0.0", - "resolve": "^1.1.7" - }, "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "postcss": "^8.0.0" + "node": ">=8" } }, - "node_modules/postcss-js": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", - "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "node_modules/detect-node-es": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", + "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==", + "dev": true + }, + "node_modules/detect-package-manager": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-package-manager/-/detect-package-manager-2.0.1.tgz", + "integrity": "sha512-j/lJHyoLlWi6G1LDdLgvUtz60Zo5GEj+sVYtTVXnYLDPuzgC3llMxonXym9zIwhhUII8vjdw0LXxavpLqTbl1A==", "dev": true, "dependencies": { - "camelcase-css": "^2.0.1" + "execa": "^5.1.1" }, "engines": { - "node": "^12 || ^14 || >= 16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": "^8.4.21" + "node": ">=12" } }, - "node_modules/postcss-load-config": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", - "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", + "node_modules/detect-port": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.5.1.tgz", + "integrity": "sha512-aBzdj76lueB6uUst5iAs7+0H/oOjqI5D16XUWxlWMIMROhcM0rfsNVk93zTngq1dDNpoXRr++Sus7ETAExppAQ==", "dev": true, "dependencies": { - "lilconfig": "^2.0.5", - "yaml": "^1.10.2" - }, - "engines": { - "node": ">= 10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": ">=8.0.9", - "ts-node": ">=9.0.0" + "address": "^1.0.1", + "debug": "4" }, - "peerDependenciesMeta": { - "postcss": { - "optional": true - }, - "ts-node": { - "optional": true - } + "bin": { + "detect": "bin/detect-port.js", + "detect-port": "bin/detect-port.js" } }, - "node_modules/postcss-merge-longhand": { - "version": "5.1.7", - "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.1.7.tgz", - "integrity": "sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ==", + "node_modules/detective": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.1.tgz", + "integrity": "sha512-v9XE1zRnz1wRtgurGu0Bs8uHKFSTdteYZNbIPFVhUZ39L/S79ppMpdmVOZAnoz1jfEFodc48n6MX483Xo3t1yw==", "dev": true, "dependencies": { - "postcss-value-parser": "^4.2.0", - "stylehacks": "^5.1.1" + "acorn-node": "^1.8.2", + "defined": "^1.0.0", + "minimist": "^1.2.6" }, - "engines": { - "node": "^10 || ^12 || >=14.0" + "bin": { + "detective": "bin/detective.js" }, - "peerDependencies": { - "postcss": "^8.2.15" + "engines": { + "node": ">=0.8.0" } }, - "node_modules/postcss-merge-rules": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.1.4.tgz", - "integrity": "sha512-0R2IuYpgU93y9lhVbO/OylTtKMVcHb67zjWIfCiKR9rWL3GUk1677LAqD/BcHizukdZEjT8Ru3oHRoAYoJy44g==", + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", "dev": true, - "dependencies": { - "browserslist": "^4.21.4", - "caniuse-api": "^3.0.0", - "cssnano-utils": "^3.1.0", - "postcss-selector-parser": "^6.0.5" - }, "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/postcss-minify-font-values": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz", - "integrity": "sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==", + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, "dependencies": { - "postcss-value-parser": "^4.2.0" + "path-type": "^4.0.0" }, "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node": ">=8" } }, - "node_modules/postcss-minify-gradients": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz", - "integrity": "sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==", - "dev": true, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dependencies": { - "colord": "^2.9.1", - "cssnano-utils": "^3.1.0", - "postcss-value-parser": "^4.2.0" + "esutils": "^2.0.2" }, "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node": ">=6.0.0" } }, - "node_modules/postcss-minify-params": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.1.4.tgz", - "integrity": "sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw==", + "node_modules/doctypes": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/doctypes/-/doctypes-1.1.0.tgz", + "integrity": "sha512-LLBi6pEqS6Do3EKQ3J0NqHWV5hhb78Pi8vvESYwyOy2c31ZEZVdtitdzsQsKb7878PEERhzUk0ftqGhG6Mz+pQ==", + "dev": true + }, + "node_modules/dom-accessibility-api": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", + "dev": true + }, + "node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", "dev": true, "dependencies": { - "browserslist": "^4.21.4", - "cssnano-utils": "^3.1.0", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" }, - "peerDependencies": { - "postcss": "^8.2.15" + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" } }, - "node_modules/postcss-minify-selectors": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz", - "integrity": "sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg==", + "node_modules/dom-serializer/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", "dev": true, "dependencies": { - "postcss-selector-parser": "^6.0.5" + "domelementtype": "^2.2.0" }, "engines": { - "node": "^10 || ^12 || >=14.0" + "node": ">= 4" }, - "peerDependencies": { - "postcss": "^8.2.15" + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" } }, - "node_modules/postcss-nested": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.0.tgz", - "integrity": "sha512-0DkamqrPcmkBDsLn+vQDIrtkSbNkv5AD/M322ySo9kqFkCIYklym2xEmWkwo+Y3/qZo34tzEPNUw4y7yMCdv5w==", + "node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", "dev": true, "dependencies": { - "postcss-selector-parser": "^6.0.10" - }, - "engines": { - "node": ">=12.0" + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": "^8.2.14" + "url": "https://github.com/fb55/domutils?sponsor=1" } }, - "node_modules/postcss-normalize-charset": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz", - "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==", + "node_modules/dotenv": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", + "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==", "dev": true, "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node": ">=12" } }, - "node_modules/postcss-normalize-display-values": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz", - "integrity": "sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==", + "node_modules/dotenv-expand": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-10.0.0.tgz", + "integrity": "sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==", "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node": ">=12" } }, - "node_modules/postcss-normalize-positions": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz", - "integrity": "sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==", + "node_modules/duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", "dev": true, "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" } }, - "node_modules/postcss-normalize-repeat-style": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz", - "integrity": "sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==", + "node_modules/duplexify/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/duplexify/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, - "node_modules/postcss-normalize-string": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz", - "integrity": "sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==", + "node_modules/duplexify/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/duplexify/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "safe-buffer": "~5.1.0" } }, - "node_modules/postcss-normalize-timing-functions": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz", - "integrity": "sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==", + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", "dev": true, "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" } }, - "node_modules/postcss-normalize-unicode": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.1.tgz", - "integrity": "sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA==", + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "dev": true + }, + "node_modules/ejs": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.9.tgz", + "integrity": "sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==", "dev": true, "dependencies": { - "browserslist": "^4.21.4", - "postcss-value-parser": "^4.2.0" + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" }, "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node": ">=0.10.0" } }, - "node_modules/postcss-normalize-url": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz", - "integrity": "sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==", - "dev": true, + "node_modules/electron-to-chromium": { + "version": "1.4.645", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.645.tgz", + "integrity": "sha512-EeS1oQDCmnYsRDRy2zTeC336a/4LZ6WKqvSaM1jLocEk5ZuyszkQtCpsqvuvaIXGOUjwtvF6LTcS8WueibXvSw==" + }, + "node_modules/element-plus": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/element-plus/-/element-plus-2.3.1.tgz", + "integrity": "sha512-IBS7ic1mRyDXpOreRkredV4ByZSuax5HPb0zNOHm4qwKC4wm927yQv+Is0JbzxPzCW5zWaV4PLy9/Gl3E3v59w==", "dependencies": { - "normalize-url": "^6.0.1", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" + "@ctrl/tinycolor": "^3.4.1", + "@element-plus/icons-vue": "^2.0.6", + "@floating-ui/dom": "^1.0.1", + "@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.7", + "@types/lodash": "^4.14.182", + "@types/lodash-es": "^4.17.6", + "@vueuse/core": "^9.1.0", + "async-validator": "^4.2.5", + "dayjs": "^1.11.3", + "escape-html": "^1.0.3", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "lodash-unified": "^1.0.2", + "memoize-one": "^6.0.0", + "normalize-wheel-es": "^1.2.0" }, "peerDependencies": { - "postcss": "^8.2.15" + "vue": "^3.2.0" } }, - "node_modules/postcss-normalize-whitespace": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz", - "integrity": "sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==", - "dev": true, + "node_modules/element-resize-detector": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/element-resize-detector/-/element-resize-detector-1.2.4.tgz", + "integrity": "sha512-Fl5Ftk6WwXE0wqCgNoseKWndjzZlDCwuPTcoVZfCP9R3EHQF8qUtr3YUPNETegRBOKqQKPW3n4kiIWngGi8tKg==", "dependencies": { - "postcss-value-parser": "^4.2.0" - }, + "batch-processor": "1.0.0" + } + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, + "node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node": ">= 4" } }, - "node_modules/postcss-ordered-values": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz", - "integrity": "sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==", + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", "dev": true, - "dependencies": { - "cssnano-utils": "^3.1.0", - "postcss-value-parser": "^4.2.0" - }, "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node": ">= 0.8" } }, - "node_modules/postcss-reduce-initial": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.1.2.tgz", - "integrity": "sha512-dE/y2XRaqAi6OvjzD22pjTUQ8eOfc6m/natGHgKFBK9DxFmIm69YmaRVQrGgFlEfc1HePIurY0TmDeROK05rIg==", + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", "dev": true, "dependencies": { - "browserslist": "^4.21.4", - "caniuse-api": "^3.0.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "once": "^1.4.0" } }, - "node_modules/postcss-reduce-transforms": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz", - "integrity": "sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==", - "dev": true, + "node_modules/engine.io-client": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.4.0.tgz", + "integrity": "sha512-GyKPDyoEha+XZ7iEqam49vz6auPnNJ9ZBfy89f+rMMas8AuiMWOZ9PVzu8xb9ZC6rafUqiGHSCfu22ih66E+1g==", "dependencies": { - "postcss-value-parser": "^4.2.0" - }, + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1", + "engine.io-parser": "~5.0.3", + "ws": "~8.11.0", + "xmlhttprequest-ssl": "~2.0.0" + } + }, + "node_modules/engine.io-parser": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.6.tgz", + "integrity": "sha512-tjuoZDMAdEhVnSFleYPCtdL2GXwVTGtNjoeJd9IhIG3C1xs9uwxqRNEu5WpnDZCaozwVlK/nuQhpodhXSIMaxw==", "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node": ">=10.0.0" } }, - "node_modules/postcss-selector-parser": { - "version": "6.0.11", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.11.tgz", - "integrity": "sha512-zbARubNdogI9j7WY4nQJBiNqQf3sLS3wCP4WfOidu+p28LofJqDH1tcXypGrcmMHhDk2t9wGhCsYe/+szLTy1g==", + "node_modules/enhanced-resolve": { + "version": "5.14.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.14.0.tgz", + "integrity": "sha512-+DCows0XNwLDcUhbFJPdlQEVnT2zXlCv7hPxemTz86/O+B/hCQ+mb7ydkPKiflpVraqLPCAfu7lDy+hBXueojw==", + "peer": true, "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" }, "engines": { - "node": ">=4" + "node": ">=10.13.0" } }, - "node_modules/postcss-svgo": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.1.0.tgz", - "integrity": "sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==", + "node_modules/enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", "dev": true, "dependencies": { - "postcss-value-parser": "^4.2.0", - "svgo": "^2.7.0" + "ansi-colors": "^4.1.1" }, "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node": ">=8.6" } }, - "node_modules/postcss-unique-selectors": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz", - "integrity": "sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.0.5" - }, + "node_modules/entities": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz", + "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==", "engines": { - "node": "^10 || ^12 || >=14.0" + "node": ">=0.12" }, - "peerDependencies": { - "postcss": "^8.2.15" + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "node_modules/envinfo": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.11.0.tgz", + "integrity": "sha512-G9/6xF1FPbIw0TtalAMaVPpiq2aDEuKLXM314jPVAO9r2fo2a4BLqMNkmRS7O/xPPZ+COAhGIz3ETvHEV3eUcg==", + "dev": true, + "bin": { + "envinfo": "dist/cli.js" + }, "engines": { - "node": ">= 0.8.0" + "node": ">=4" } }, - "node_modules/pretty-bytes": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", - "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.21.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz", + "integrity": "sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==", + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-set-tostringtag": "^2.0.1", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.2.0", + "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.10", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.4.3", + "safe-regex-test": "^1.0.0", + "string.prototype.trim": "^1.2.7", + "string.prototype.trimend": "^1.0.6", + "string.prototype.trimstart": "^1.0.6", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.9" + }, "engines": { - "node": ">=6" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "node_modules/es-get-iterator": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", + "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", "dependencies": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - } - }, - "node_modules/property-expr": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.5.tgz", - "integrity": "sha512-IJUkICM5dP5znhCckHSv30Q4b5/JA5enCtkRHYaOVOAocnH/1BQEYTC5NMfT3AVl/iXKdr3aqQbQn9DxyWknwA==" - }, - "node_modules/prosemirror-changeset": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/prosemirror-changeset/-/prosemirror-changeset-2.2.0.tgz", - "integrity": "sha512-QM7ohGtkpVpwVGmFb8wqVhaz9+6IUXcIQBGZ81YNAKYuHiFJ1ShvSzab4pKqTinJhwciZbrtBEk/2WsqSt2PYg==", - "dependencies": { - "prosemirror-transform": "^1.0.0" - } - }, - "node_modules/prosemirror-collab": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/prosemirror-collab/-/prosemirror-collab-1.3.0.tgz", - "integrity": "sha512-+S/IJ69G2cUu2IM5b3PBekuxs94HO1CxJIWOFrLQXUaUDKL/JfBx+QcH31ldBlBXyDEUl+k3Vltfi1E1MKp2mA==", - "dependencies": { - "prosemirror-state": "^1.0.0" - } - }, - "node_modules/prosemirror-commands": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/prosemirror-commands/-/prosemirror-commands-1.5.1.tgz", - "integrity": "sha512-ga1ga/RkbzxfAvb6iEXYmrEpekn5NCwTb8w1dr/gmhSoaGcQ0VPuCzOn5qDEpC45ql2oDkKoKQbRxLJwKLpMTQ==", - "dependencies": { - "prosemirror-model": "^1.0.0", - "prosemirror-state": "^1.0.0", - "prosemirror-transform": "^1.0.0" - } - }, - "node_modules/prosemirror-dropcursor": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/prosemirror-dropcursor/-/prosemirror-dropcursor-1.8.0.tgz", - "integrity": "sha512-TZMitR8nlp9Xh42pDYGcWopCoFPmJduoyGJ7FjYM2/7gZKnfD41TIaZN5Q1cQjm6Fm/P5vk/DpVYFhS8kDdigw==", - "dependencies": { - "prosemirror-state": "^1.0.0", - "prosemirror-transform": "^1.1.0", - "prosemirror-view": "^1.1.0" - } - }, - "node_modules/prosemirror-gapcursor": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/prosemirror-gapcursor/-/prosemirror-gapcursor-1.3.1.tgz", - "integrity": "sha512-GKTeE7ZoMsx5uVfc51/ouwMFPq0o8YrZ7Hx4jTF4EeGbXxBveUV8CGv46mSHuBBeXGmvu50guoV2kSnOeZZnUA==", - "dependencies": { - "prosemirror-keymap": "^1.0.0", - "prosemirror-model": "^1.0.0", - "prosemirror-state": "^1.0.0", - "prosemirror-view": "^1.0.0" - } - }, - "node_modules/prosemirror-history": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/prosemirror-history/-/prosemirror-history-1.3.1.tgz", - "integrity": "sha512-YMV/IWBZ+LZSfaNcBbPcaQUiAiJRYFyJW2aapuNzL8nhIRsI7fIO0ykJFSe802+mWeoTsVJ1jxvRWPYqaUqljQ==", - "dependencies": { - "prosemirror-state": "^1.2.2", - "prosemirror-transform": "^1.0.0", - "prosemirror-view": "^1.31.0", - "rope-sequence": "^1.3.0" - } - }, - "node_modules/prosemirror-inputrules": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/prosemirror-inputrules/-/prosemirror-inputrules-1.2.0.tgz", - "integrity": "sha512-eAW/M/NTSSzpCOxfR8Abw6OagdG0MiDAiWHQMQveIsZtoKVYzm0AflSPq/ymqJd56/Su1YPbwy9lM13wgHOFmQ==", - "dependencies": { - "prosemirror-state": "^1.0.0", - "prosemirror-transform": "^1.0.0" + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "is-arguments": "^1.1.1", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.7", + "isarray": "^2.0.5", + "stop-iteration-iterator": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/prosemirror-keymap": { + "node_modules/es-module-lexer": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prosemirror-keymap/-/prosemirror-keymap-1.2.1.tgz", - "integrity": "sha512-kVK6WGC+83LZwuSJnuCb9PsADQnFZllt94qPP3Rx/vLcOUV65+IbBeH2nS5cFggPyEVJhGkGrgYFRrG250WhHQ==", - "dependencies": { - "prosemirror-state": "^1.0.0", - "w3c-keyname": "^2.2.0" - } - }, - "node_modules/prosemirror-markdown": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/prosemirror-markdown/-/prosemirror-markdown-1.10.1.tgz", - "integrity": "sha512-s7iaTLiX+qO5z8kF2NcMmy2T7mIlxzkS4Sp3vTKSYChPtbMpg6YxFkU0Y06rUg2WtKlvBu7v1bXzlGBkfjUWAA==", - "dependencies": { - "markdown-it": "^13.0.1", - "prosemirror-model": "^1.0.0" - } + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.2.1.tgz", + "integrity": "sha512-9978wrXM50Y4rTMmW5kXIC09ZdXQZqkE4mxhwkd8VbzsGkXGPgV4zWuqQJgCEzYngdo2dYDa0l8xhX4fkSwJSg==", + "peer": true }, - "node_modules/prosemirror-menu": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prosemirror-menu/-/prosemirror-menu-1.2.1.tgz", - "integrity": "sha512-sBirXxVfHalZO4f1ZS63WzewINK4182+7dOmoMeBkqYO8wqMBvBS7wQuwVOHnkMWPEh0+N0LJ856KYUN+vFkmQ==", + "node_modules/es-set-tostringtag": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", + "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", "dependencies": { - "crelt": "^1.0.0", - "prosemirror-commands": "^1.0.0", - "prosemirror-history": "^1.0.0", - "prosemirror-state": "^1.0.0" + "get-intrinsic": "^1.1.3", + "has": "^1.0.3", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" } }, - "node_modules/prosemirror-model": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.19.0.tgz", - "integrity": "sha512-/CvFGJnwc41EJSfDkQLly1cAJJJmBpZwwUJtwZPTjY2RqZJfM8HVbCreOY/jti8wTRbVyjagcylyGoeJH/g/3w==", + "node_modules/es-shim-unscopables": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", + "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", "dependencies": { - "orderedmap": "^2.0.0" + "has": "^1.0.3" } }, - "node_modules/prosemirror-schema-basic": { + "node_modules/es-to-primitive": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prosemirror-schema-basic/-/prosemirror-schema-basic-1.2.1.tgz", - "integrity": "sha512-vYBdIHsYKSDIqYmPBC7lnwk9DsKn8PnVqK97pMYP5MLEDFqWIX75JiaJTzndBii4bRuNqhC2UfDOfM3FKhlBHg==", - "dependencies": { - "prosemirror-model": "^1.19.0" - } - }, - "node_modules/prosemirror-schema-list": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/prosemirror-schema-list/-/prosemirror-schema-list-1.2.2.tgz", - "integrity": "sha512-rd0pqSDp86p0MUMKG903g3I9VmElFkQpkZ2iOd3EOVg1vo5Cst51rAsoE+5IPy0LPXq64eGcCYlW1+JPNxOj2w==", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", "dependencies": { - "prosemirror-model": "^1.0.0", - "prosemirror-state": "^1.0.0", - "prosemirror-transform": "^1.0.0" + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/prosemirror-state": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/prosemirror-state/-/prosemirror-state-1.4.2.tgz", - "integrity": "sha512-puuzLD2mz/oTdfgd8msFbe0A42j5eNudKAAPDB0+QJRw8cO1ygjLmhLrg9RvDpf87Dkd6D4t93qdef00KKNacQ==", - "dependencies": { - "prosemirror-model": "^1.0.0", - "prosemirror-transform": "^1.0.0", - "prosemirror-view": "^1.27.0" + "node_modules/esbuild": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.17.tgz", + "integrity": "sha512-1GJtYnUxsJreHYA0Y+iQz2UEykonY66HNWOb0yXYZi9/kNrORUEHVg87eQsCtqh59PEJ5YVZJO98JHznMJSWjg==", + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.18.17", + "@esbuild/android-arm64": "0.18.17", + "@esbuild/android-x64": "0.18.17", + "@esbuild/darwin-arm64": "0.18.17", + "@esbuild/darwin-x64": "0.18.17", + "@esbuild/freebsd-arm64": "0.18.17", + "@esbuild/freebsd-x64": "0.18.17", + "@esbuild/linux-arm": "0.18.17", + "@esbuild/linux-arm64": "0.18.17", + "@esbuild/linux-ia32": "0.18.17", + "@esbuild/linux-loong64": "0.18.17", + "@esbuild/linux-mips64el": "0.18.17", + "@esbuild/linux-ppc64": "0.18.17", + "@esbuild/linux-riscv64": "0.18.17", + "@esbuild/linux-s390x": "0.18.17", + "@esbuild/linux-x64": "0.18.17", + "@esbuild/netbsd-x64": "0.18.17", + "@esbuild/openbsd-x64": "0.18.17", + "@esbuild/sunos-x64": "0.18.17", + "@esbuild/win32-arm64": "0.18.17", + "@esbuild/win32-ia32": "0.18.17", + "@esbuild/win32-x64": "0.18.17" } }, - "node_modules/prosemirror-tables": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/prosemirror-tables/-/prosemirror-tables-1.3.2.tgz", - "integrity": "sha512-/9JTeN6s58Zq66HXaxP6uf8PAmc7XXKZFPlOGVtLvxEd6xBP6WtzaJB9wBjiGUzwbdhdMEy7V62yuHqk/3VrnQ==", - "dependencies": { - "prosemirror-keymap": "^1.1.2", - "prosemirror-model": "^1.8.1", - "prosemirror-state": "^1.3.1", - "prosemirror-transform": "^1.2.1", - "prosemirror-view": "^1.13.3" - } + "node_modules/esbuild-plugin-alias": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/esbuild-plugin-alias/-/esbuild-plugin-alias-0.2.1.tgz", + "integrity": "sha512-jyfL/pwPqaFXyKnj8lP8iLk6Z0m099uXR45aSN8Av1XD4vhvQutxxPzgA2bTcAwQpa1zCXDcWOlhFgyP3GKqhQ==", + "dev": true }, - "node_modules/prosemirror-trailing-node": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/prosemirror-trailing-node/-/prosemirror-trailing-node-2.0.4.tgz", - "integrity": "sha512-0Yl9w7IdHkaCdqR+NE3FOucePME4OmiGcybnF1iasarEILP5U8+4xTnl53yafULjmwcg1SrSG65Hg7Zk2H2v3g==", + "node_modules/esbuild-register": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/esbuild-register/-/esbuild-register-3.5.0.tgz", + "integrity": "sha512-+4G/XmakeBAsvJuDugJvtyF1x+XJT4FMocynNpxrvEBViirpfUn2PgNpCHedfWhF4WokNsO/OvMKrmJOIJsI5A==", + "dev": true, "dependencies": { - "@babel/runtime": "^7.21.0", - "@remirror/core-constants": "^2.0.1", - "@remirror/core-helpers": "^2.0.2", - "escape-string-regexp": "^4.0.0" + "debug": "^4.3.4" }, "peerDependencies": { - "prosemirror-model": "^1.19.0", - "prosemirror-state": "^1.4.2", - "prosemirror-view": "^1.30.2" + "esbuild": ">=0.12 <1" } }, - "node_modules/prosemirror-trailing-node/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6" } }, - "node_modules/prosemirror-transform": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/prosemirror-transform/-/prosemirror-transform-1.7.1.tgz", - "integrity": "sha512-VteoifAfpt46z0yEt6Fc73A5OID9t/y2QIeR5MgxEwTuitadEunD/V0c9jQW8ziT8pbFM54uTzRLJ/nLuQjMxg==", - "dependencies": { - "prosemirror-model": "^1.0.0" + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" } }, - "node_modules/prosemirror-view": { - "version": "1.31.2", - "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.31.2.tgz", - "integrity": "sha512-d/HKgUsaKzMQnr5tGRdZq+8GSixOTyYI69hoNV417VlciTvUDFSr4SWsRNUzhMRwvT6xVLI8yrVWERHjNWI6uw==", - "dependencies": { - "prosemirror-model": "^1.16.0", - "prosemirror-state": "^1.0.0", - "prosemirror-transform": "^1.1.0" - } - }, - "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": "sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A==", - "dev": true - }, - "node_modules/psl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", - "dev": true - }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, + "node_modules/eslint": { + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.36.0.tgz", + "integrity": "sha512-Y956lmS7vDqomxlaaQAHVmeb4tNMp2FWIvU/RnU5BD3IKMD/MJPr76xdyr68P8tV1iNMvN2mRK0yy3c+UjL+bw==", "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.4.0", + "@eslint/eslintrc": "^2.0.1", + "@eslint/js": "8.36.0", + "@humanwhocodes/config-array": "^0.11.8", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.1.1", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.5.0", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-sdsl": "^4.1.4", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, "engines": { - "node": ">=6" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/qs": { - "version": "6.11.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.1.tgz", - "integrity": "sha512-0wsrzgTz/kAVIeuxSjnpGC56rzYtr6JT/2BwEvMaPhFIoYa1aGO8LbzuU1R0uUYQkLpWBTOj0l/CLAJB64J6nQ==", + "node_modules/eslint-config-airbnb-base": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz", + "integrity": "sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==", "dependencies": { - "side-channel": "^1.0.4" + "confusing-browser-globals": "^1.0.10", + "object.assign": "^4.1.2", + "object.entries": "^1.1.5", + "semver": "^6.3.0" }, "engines": { - "node": ">=0.6" + "node": "^10.12.0 || >=12.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "eslint": "^7.32.0 || ^8.2.0", + "eslint-plugin-import": "^2.25.2" } }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "dev": true, + "node_modules/eslint-import-resolver-alias": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-alias/-/eslint-import-resolver-alias-1.1.2.tgz", + "integrity": "sha512-WdviM1Eu834zsfjHtcGHtGfcu+F30Od3V7I9Fi57uhBEwPkjDcii7/yW8jAT+gOhn4P/vOxxNAXbFAKsrrc15w==", "engines": { - "node": ">=10" + "node": ">= 4" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "eslint-plugin-import": ">=1.4.0" } }, - "node_modules/ramda": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.27.2.tgz", - "integrity": "sha512-SbiLPU40JuJniHexQSAgad32hfwd+DRUdwF2PlVuI5RZD0/vahUco7R8vD86J/tcEKKF9vZrUVwgtmGCqlCKyA==" - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "node_modules/eslint-import-resolver-custom-alias": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-custom-alias/-/eslint-import-resolver-custom-alias-1.3.0.tgz", + "integrity": "sha512-9rrpduF6/SZHFXrJgjeA+edJek6xulplYfo/UJvLPrY38O9UY00rAq76dHRnZ289yftc5NIfx3THi0IILRQ3dg==", "dependencies": { - "safe-buffer": "^5.1.0" + "glob-parent": "^5.1.0", + "resolve": "^1.3.0" + }, + "peerDependencies": { + "eslint-plugin-import": ">=2.2.0" } }, - "node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, - "node_modules/read-cache": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", - "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", - "dev": true, + "node_modules/eslint-import-resolver-custom-alias/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dependencies": { - "pify": "^2.3.0" + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" } }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "devOptional": true, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz", + "integrity": "sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==", "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" + "debug": "^3.2.7", + "is-core-module": "^2.11.0", + "resolve": "^1.22.1" } }, - "node_modules/regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } }, - "node_modules/regexp.prototype.flags": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", - "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "node_modules/eslint-module-utils": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz", + "integrity": "sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "functions-have-names": "^1.2.2" + "debug": "^3.2.7" }, "engines": { - "node": ">= 0.4" + "node": ">=4" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependenciesMeta": { + "eslint": { + "optional": true + } } }, - "node_modules/replace-in-file": { - "version": "6.3.5", - "resolved": "https://registry.npmjs.org/replace-in-file/-/replace-in-file-6.3.5.tgz", - "integrity": "sha512-arB9d3ENdKva2fxRnSjwBEXfK1npgyci7ZZuwysgAp7ORjHSyxz6oqIjTEv8R0Ydl4Ll7uOAZXL4vbkhGIizCg==", - "dev": true, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dependencies": { - "chalk": "^4.1.2", - "glob": "^7.2.0", - "yargs": "^17.2.1" - }, - "bin": { - "replace-in-file": "bin/cli.js" - }, - "engines": { - "node": ">=10" + "ms": "^2.1.1" } }, - "node_modules/replace-in-file/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/eslint-plugin-cypress": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-cypress/-/eslint-plugin-cypress-2.12.1.tgz", + "integrity": "sha512-c2W/uPADl5kospNDihgiLc7n87t5XhUbFDoTl6CfVkmG+kDAb5Ux10V9PoLPu9N+r7znpc+iQlcmAqT1A/89HA==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "globals": "^11.12.0" }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "peerDependencies": { + "eslint": ">= 3.2.1" } }, - "node_modules/replace-in-file/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, + "node_modules/eslint-plugin-import": { + "version": "2.27.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz", + "integrity": "sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "array.prototype.flatmap": "^1.3.1", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.7", + "eslint-module-utils": "^2.7.4", + "has": "^1.0.3", + "is-core-module": "^2.11.0", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.values": "^1.1.6", + "resolve": "^1.22.1", + "semver": "^6.3.0", + "tsconfig-paths": "^3.14.1" }, "engines": { - "node": ">=10" + "node": ">=4" }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" } }, - "node_modules/replace-in-file/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" + "ms": "^2.1.1" } }, - "node_modules/replace-in-file/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/replace-in-file/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, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dependencies": { + "esutils": "^2.0.2" + }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/replace-in-file/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, + "node_modules/eslint-plugin-jsx-a11y": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.7.1.tgz", + "integrity": "sha512-63Bog4iIethyo8smBklORknVjB0T2dwB8Mr/hIC+fBS0uyHdYYpzM/Ed+YC8VxTjlXHEWFOdmgwcDn1U2L9VCA==", "dependencies": { - "has-flag": "^4.0.0" + "@babel/runtime": "^7.20.7", + "aria-query": "^5.1.3", + "array-includes": "^3.1.6", + "array.prototype.flatmap": "^1.3.1", + "ast-types-flow": "^0.0.7", + "axe-core": "^4.6.2", + "axobject-query": "^3.1.1", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "has": "^1.0.3", + "jsx-ast-utils": "^3.3.3", + "language-tags": "=1.0.5", + "minimatch": "^3.1.2", + "object.entries": "^1.1.6", + "object.fromentries": "^2.0.6", + "semver": "^6.3.0" }, "engines": { - "node": ">=8" + "node": ">=4.0" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" } }, - "node_modules/request-progress": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz", - "integrity": "sha512-MnWzEHHaxHO2iWiQuHrUPBi/1WeBf5PkxQqNyNvLl9VAYSdXkP8tQ3pBSeCPD+yw0v0Aq1zosWLz0BdeXpWwZg==", - "dev": true, + "node_modules/eslint-plugin-react": { + "version": "7.32.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.32.2.tgz", + "integrity": "sha512-t2fBMa+XzonrrNkyVirzKlvn5RXzzPwRHtMvLAtVZrt8oxgnTQaYbU6SXTOO1mwQgp1y5+toMSKInnzGr0Knqg==", "dependencies": { - "throttleit": "^1.0.0" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, + "array-includes": "^3.1.6", + "array.prototype.flatmap": "^1.3.1", + "array.prototype.tosorted": "^1.1.1", + "doctrine": "^2.1.0", + "estraverse": "^5.3.0", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.6", + "object.fromentries": "^2.0.6", + "object.hasown": "^1.1.2", + "object.values": "^1.1.6", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.4", + "semver": "^6.3.0", + "string.prototype.matchall": "^4.0.8" + }, "engines": { - "node": ">=0.10.0" + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" } }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, + "node_modules/eslint-plugin-react/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dependencies": { + "esutils": "^2.0.2" + }, "engines": { "node": ">=0.10.0" } }, - "node_modules/resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.4", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz", + "integrity": "sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==", "dependencies": { "is-core-module": "^2.9.0", "path-parse": "^1.0.7", @@ -9870,288 +11450,214 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "engines": { - "node": ">=4" - } - }, - "node_modules/resolve-path": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/resolve-path/-/resolve-path-1.4.0.tgz", - "integrity": "sha512-i1xevIst/Qa+nA9olDxLWnLk8YZbi8R/7JPbCMcgyWaFR6bKWaexgJgEB5oc2PKMjYdrHynyz0NY+if+H98t1w==", + "node_modules/eslint-plugin-storybook": { + "version": "0.6.15", + "resolved": "https://registry.npmjs.org/eslint-plugin-storybook/-/eslint-plugin-storybook-0.6.15.tgz", + "integrity": "sha512-lAGqVAJGob47Griu29KXYowI4G7KwMoJDOkEip8ujikuDLxU+oWJ1l0WL6F2oDO4QiyUFXvtDkEkISMOPzo+7w==", "dev": true, "dependencies": { - "http-errors": "~1.6.2", - "path-is-absolute": "1.0.1" + "@storybook/csf": "^0.0.1", + "@typescript-eslint/utils": "^5.45.0", + "requireindex": "^1.1.0", + "ts-dedent": "^2.2.0" }, "engines": { - "node": ">= 0.8" + "node": "12.x || 14.x || >= 16" + }, + "peerDependencies": { + "eslint": ">=6" } }, - "node_modules/resolve-path/node_modules/http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "node_modules/eslint-plugin-storybook/node_modules/@storybook/csf": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/@storybook/csf/-/csf-0.0.1.tgz", + "integrity": "sha512-USTLkZze5gkel8MYCujSRBVIrUQ3YPBrLOx7GNk/0wttvVtlzWXAq9eLbQ4p/NicGxP+3T7KPEMVV//g+yubpw==", "dev": true, "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - }, - "engines": { - "node": ">= 0.6" + "lodash": "^4.17.15" } }, - "node_modules/resolve-path/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", - "dev": true - }, - "node_modules/resolve-path/node_modules/setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true - }, - "node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, + "node_modules/eslint-plugin-vue": { + "version": "9.10.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.10.0.tgz", + "integrity": "sha512-2MgP31OBf8YilUvtakdVMc8xVbcMp7z7/iQj8LHVpXrSXHPXSJRUIGSPFI6b6pyCx/buKaFJ45ycqfHvQRiW2g==", "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" + "@eslint-community/eslint-utils": "^4.3.0", + "natural-compare": "^1.4.0", + "nth-check": "^2.0.1", + "postcss-selector-parser": "^6.0.9", + "semver": "^7.3.5", + "vue-eslint-parser": "^9.0.1", + "xml-name-validator": "^4.0.0" }, "engines": { - "node": ">=8" + "node": "^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "node_modules/eslint-plugin-vue/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" + "node": ">=10" } }, - "node_modules/rfdc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", - "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", - "dev": true - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "node_modules/eslint-plugin-vue/node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", "dependencies": { - "glob": "^7.1.3" + "lru-cache": "^6.0.0" }, "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rollup": { - "version": "3.26.3", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.26.3.tgz", - "integrity": "sha512-7Tin0C8l86TkpcMtXvQu6saWH93nhG3dGQ1/+l5V2TDMceTxO7kDiK6GzbfLWNNxqJXm591PcEZUozZm51ogwQ==", - "bin": { - "rollup": "dist/bin/rollup" + "semver": "bin/semver.js" }, "engines": { - "node": ">=14.18.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" + "node": ">=10" } }, - "node_modules/rollup-plugin-visualizer": { - "version": "5.9.2", - "resolved": "https://registry.npmjs.org/rollup-plugin-visualizer/-/rollup-plugin-visualizer-5.9.2.tgz", - "integrity": "sha512-waHktD5mlWrYFrhOLbti4YgQCn1uR24nYsNuXxg7LkPH8KdTXVWR9DNY1WU0QqokyMixVXJS4J04HNrVTMP01A==", - "dev": true, + "node_modules/eslint-plugin-vue/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/eslint-plugin-vuejs-accessibility": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-vuejs-accessibility/-/eslint-plugin-vuejs-accessibility-1.2.0.tgz", + "integrity": "sha512-wF7kT22lS2VOmIpDeI65bnFFKFgESEEpI+CWKr43mdfDRywA4sCk7cKhtZsvfbPOtKO0GDlnpFxZbOIGsFn7IQ==", "dependencies": { - "open": "^8.4.0", - "picomatch": "^2.3.1", - "source-map": "^0.7.4", - "yargs": "^17.5.1" - }, - "bin": { - "rollup-plugin-visualizer": "dist/bin/cli.js" - }, - "engines": { - "node": ">=14" + "aria-query": "^5.0.0", + "emoji-regex": "^10.0.0", + "vue-eslint-parser": "^9.0.1" }, "peerDependencies": { - "rollup": "2.x || 3.x" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "node_modules/rollup-plugin-visualizer/node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", - "dev": true, - "engines": { - "node": ">= 8" + "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/rope-sequence": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/rope-sequence/-/rope-sequence-1.3.3.tgz", - "integrity": "sha512-85aZYCxweiD5J8yTEbw+E6A27zSnLPNDL0WfPdw3YYodq7WjnTKo0q4dtyQ2gz23iPT8Q9CUyJtAaUNcTxRf5Q==" + "node_modules/eslint-plugin-vuejs-accessibility/node_modules/emoji-regex": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.2.1.tgz", + "integrity": "sha512-97g6QgOk8zlDRdgq1WxwgTMgEWGVAQvB5Fdpgc1MkNy56la5SKP9GsMXKDOdqwn90/41a8yPwIGk1Y6WVbeMQA==" }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], + "node_modules/eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", "dependencies": { - "queue-microtask": "^1.2.2" + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/rxjs": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.0.tgz", - "integrity": "sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==", - "dev": true, - "dependencies": { - "tslib": "^2.1.0" + "node_modules/eslint-visitor-keys": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safe-regex-test": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", - "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "is-regex": "^1.1.4" + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "node_modules/sanitize-html": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.10.0.tgz", - "integrity": "sha512-JqdovUd81dG4k87vZt6uA6YhDfWkUGruUu/aPmXLxXi45gZExnt9Bnw/qeQU8oGf82vPyaE0vO4aH0PbobB9JQ==", - "dependencies": { - "deepmerge": "^4.2.2", - "escape-string-regexp": "^4.0.0", - "htmlparser2": "^8.0.0", - "is-plain-object": "^5.0.0", - "parse-srcset": "^1.0.2", - "postcss": "^8.3.11" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/sanitize-html/node_modules/dom-serializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", - "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "entities": "^4.2.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" }, "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/sanitize-html/node_modules/domhandler": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", - "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "node_modules/eslint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dependencies": { - "domelementtype": "^2.3.0" + "color-name": "~1.1.4" }, "engines": { - "node": ">= 4" + "node": ">=7.0.0" + } + }, + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "engines": { + "node": ">=10" }, "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/sanitize-html/node_modules/domutils": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz", - "integrity": "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==", + "node_modules/eslint/node_modules/globals": { + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", "dependencies": { - "dom-serializer": "^2.0.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.1" + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" }, "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/sanitize-html/node_modules/entities": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", - "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==", + "node_modules/eslint/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==", "engines": { - "node": ">=0.12" + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "engines": { + "node": ">=8" } }, - "node_modules/sanitize-html/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "node_modules/eslint/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "engines": { "node": ">=10" }, @@ -10159,881 +11665,1058 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/sanitize-html/node_modules/htmlparser2": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", - "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], + "node_modules/espree": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.0.tgz", + "integrity": "sha512-JPbJGhKc47++oo4JkEoTe2wjy4fmMwvFpgJT9cQzmfXKp22Dr6Hf1tdCteLz1h0P3t+mGvWZ+4Uankvh8+c6zw==", "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1", - "entities": "^4.4.0" + "acorn": "^8.8.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/sass": { - "version": "1.60.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.60.0.tgz", - "integrity": "sha512-updbwW6fNb5gGm8qMXzVO7V4sWf7LMXnMly/JEyfbfERbVH46Fn6q02BX7/eHTdKpE7d+oTkMMQpFWNUMfFbgQ==", - "devOptional": true, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "dependencies": { - "chokidar": ">=3.0.0 <4.0.0", - "immutable": "^4.0.0", - "source-map-js": ">=0.6.2 <2.0.0" + "estraverse": "^5.1.0" }, - "bin": { - "sass": "sass.js" + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dependencies": { + "estraverse": "^5.2.0" }, "engines": { - "node": ">=12.0.0" + "node": ">=4.0" } }, - "node_modules/scule": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/scule/-/scule-1.0.0.tgz", - "integrity": "sha512-4AsO/FrViE/iDNEPaAQlb77tf0csuq27EsVpy6ett584EcRTp6pTDLoGWVxCD77y5iU5FauOvhsI4o1APwPoSQ==", - "dev": true + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "engines": { + "node": ">=4.0" + } }, - "node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "bin": { - "semver": "bin/semver.js" + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "engines": { + "node": ">=0.10.0" } }, - "node_modules/serialize-javascript": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", - "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", - "dependencies": { - "randombytes": "^2.1.0" + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "dev": true, + "engines": { + "node": ">= 0.6" } }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "node_modules/eventemitter2": { + "version": "6.4.7", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.7.tgz", + "integrity": "sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg==", "dev": true }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "peer": true, + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, "dependencies": { - "shebang-regex": "^3.0.0" + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "node_modules/execa/node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, "engines": { - "node": ">=8" + "node": ">=10.17.0" } }, - "node_modules/shell-quote": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.0.tgz", - "integrity": "sha512-QHsz8GgQIGKlRi24yFc6a6lN69Idnx634w49ay6+jA5yFh7a1UY+4Rp6HPx/L/1zcEDPEij8cIsiqR6bQsE5VQ==", + "node_modules/executable": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/executable/-/executable-4.1.1.tgz", + "integrity": "sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==", "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "dependencies": { + "pify": "^2.2.0" + }, + "engines": { + "node": ">=4" } }, - "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "node_modules/express": { + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "dev": true, + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.1", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.5.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">= 0.10.0" } }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "node_modules/express/node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "dev": true, "engines": { - "node": ">=8" + "node": ">= 0.8" } }, - "node_modules/slice-ansi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", - "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", + "node_modules/express/node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "dev": true, "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" }, "engines": { - "node": ">=8" + "node": ">= 0.8" } }, - "node_modules/slice-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/express/node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", + "dev": true + }, + "node_modules/express/node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "side-channel": "^1.0.4" }, "engines": { - "node": ">=8" + "node": ">=0.6" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/slice-ansi/node_modules/color-convert": { + "node_modules/express/node_modules/statuses": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, "engines": { - "node": ">=7.0.0" + "node": ">= 0.8" } }, - "node_modules/slice-ansi/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", "dev": true }, - "node_modules/socket.io-client": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.6.1.tgz", - "integrity": "sha512-5UswCV6hpaRsNg5kkEHVcbBIXEYoVbMQaHJBXJCyEQ+CiFPV1NIOY0XOFWG4XR4GZcB8Kn6AsRs/9cy9TbqVMQ==", + "node_modules/extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "dev": true, "dependencies": { - "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.3.2", - "engine.io-client": "~6.4.0", - "socket.io-parser": "~4.2.1" + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" }, "engines": { - "node": ">=10.0.0" + "node": ">= 10.17.0" + }, + "optionalDependencies": { + "@types/yauzl": "^2.9.1" } }, - "node_modules/socket.io-parser": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.2.tgz", - "integrity": "sha512-DJtziuKypFkMMHCm2uIshOYC7QaylbtzQwiMYDuCKy3OPkjLzu4B2vAhTlqipRHHzrI0NJeBAizTK7X+6m1jVw==", + "node_modules/extract-zip/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, "dependencies": { - "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.3.1" + "pump": "^3.0.0" }, "engines": { - "node": ">=10.0.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/sortablejs": { - "version": "1.14.0", - "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.14.0.tgz", - "integrity": "sha512-pBXvQCs5/33fdN1/39pPL0NZF20LeRbLQ5jtnheIPN9JQAaufGjKdWduZn4U7wCtVuzKhmRkI0DFYHYRbB2H1w==" + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", + "dev": true, + "engines": [ + "node >=0.6.0" + ] }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/fast-glob": { + "version": "3.2.12", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", + "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, "engines": { - "node": ">=0.10.0" + "node": ">=8.6.0" } }, - "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 6" } }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" + }, + "node_modules/fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + "reusify": "^1.0.4" } }, - "node_modules/spawn-command": { - "version": "0.0.2-1", - "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz", - "integrity": "sha512-n98l9E2RMSJ9ON1AKisHzz7V42VDiBQGY6PB1BwRglz99wpVsSuGzQ+jOi6lFXBGVTCrRpltvjm+/XA+tpeJrg==", - "dev": true + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "dependencies": { + "bser": "2.1.1" + } }, - "node_modules/sshpk": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", - "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", "dev": true, "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - }, - "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" - }, - "engines": { - "node": ">=0.10.0" + "pend": "~1.2.0" } }, - "node_modules/stable": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", - "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", - "deprecated": "Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility", + "node_modules/fetch-retry": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/fetch-retry/-/fetch-retry-5.0.6.tgz", + "integrity": "sha512-3yurQZ2hD9VISAhJJP9bpYFNQrHHBXE2JxxjY5aLEcDi46RmAzJE2OC9FAde0yis5ElW0jTTzs0zfg/Cca4XqQ==", "dev": true }, - "node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/stop-iteration-iterator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", - "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", "dependencies": { - "internal-slot": "^1.0.4" + "escape-string-regexp": "^1.0.5" }, "engines": { - "node": ">= 0.4" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "flat-cache": "^3.0.4" }, "engines": { - "node": ">=8" + "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/string-width/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "node_modules/file-saver": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.2.tgz", + "integrity": "sha512-Wz3c3XQ5xroCxd1G8b7yL0Ehkf0TC9oYC6buPFkNnU9EnaPlifeAFCyCh+iewXTyFRcg0a6j3J7FmJsIhlhBdw==" }, - "node_modules/string.prototype.matchall": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz", - "integrity": "sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==", + "node_modules/file-system-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/file-system-cache/-/file-system-cache-2.3.0.tgz", + "integrity": "sha512-l4DMNdsIPsVnKrgEXbJwDJsA5mB8rGwHYERMgqQx/xAUtChPJMre1bXBzDEqqVbWv9AIbFezXMxeEkZDSrXUOQ==", + "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.3", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", - "regexp.prototype.flags": "^1.4.3", - "side-channel": "^1.0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "fs-extra": "11.1.1", + "ramda": "0.29.0" } }, - "node_modules/string.prototype.trim": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", - "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", + "node_modules/file-system-cache/node_modules/fs-extra": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", + "integrity": "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==", + "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, "engines": { - "node": ">= 0.4" - }, + "node": ">=14.14" + } + }, + "node_modules/file-system-cache/node_modules/ramda": { + "version": "0.29.0", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.0.tgz", + "integrity": "sha512-BBea6L67bYLtdbOqfp8f58fPMqEwx0doL+pAi8TZyp2YWz8R9G8z9x75CZI8W+ftqhFHCpEX2cRnUUXK130iKA==", + "dev": true, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/ramda" } }, - "node_modules/string.prototype.trimend": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", - "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "minimatch": "^5.0.1" } }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", - "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", + "node_modules/filelist/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "balanced-match": "^1.0.0" + } + }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=10" } }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "devOptional": true, "dependencies": { - "ansi-regex": "^5.0.1" + "to-regex-range": "^5.0.1" }, "engines": { "node": ">=8" } }, - "node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "engines": { - "node": ">=4" + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" } }, - "node_modules/strip-final-newline": { + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/finalhandler/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", "dev": true, "engines": { - "node": ">=6" + "node": ">= 0.8" } }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "node_modules/find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + }, "engines": { "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/avajs/find-cache-dir?sponsor=1" } }, - "node_modules/strip-literal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-1.0.1.tgz", - "integrity": "sha512-QZTsipNpa2Ppr6v1AmJHESqJ3Uz247MUS0OjrnnZjFAvEoWqxuyFuXn2xLgMtRnijJShAa1HL0gtJyUs7u7n3Q==", + "node_modules/find-cache-dir/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "dependencies": { - "acorn": "^8.8.2" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" }, - "funding": { - "url": "https://github.com/sponsors/antfu" + "engines": { + "node": ">=8" } }, - "node_modules/stylehacks": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.1.tgz", - "integrity": "sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==", + "node_modules/find-cache-dir/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "dependencies": { - "browserslist": "^4.21.4", - "postcss-selector-parser": "^6.0.4" + "p-locate": "^4.1.0" }, "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" + "node": ">=8" } }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/find-cache-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, "dependencies": { - "has-flag": "^3.0.0" + "p-try": "^2.0.0" }, "engines": { - "node": ">=4" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "engines": { - "node": ">= 0.4" + "node": ">=6" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/svgo": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", - "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", + "node_modules/find-cache-dir/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "dependencies": { - "@trysound/sax": "0.2.0", - "commander": "^7.2.0", - "css-select": "^4.1.3", - "css-tree": "^1.1.3", - "csso": "^4.2.0", - "picocolors": "^1.0.0", - "stable": "^0.1.8" - }, - "bin": { - "svgo": "bin/svgo" + "p-limit": "^2.2.0" }, "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/svgo/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true, - "engines": { - "node": ">= 10" + "node": ">=8" } }, - "node_modules/tailwind-config-viewer": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/tailwind-config-viewer/-/tailwind-config-viewer-1.7.2.tgz", - "integrity": "sha512-3JJCeAAlvG+i/EBj+tQb0x4weo30QjdSAo4hlcnVbtD+CkpzHi/UwU9InbPMcYH+ESActoa2kCyjpLEyjEkn0Q==", + "node_modules/find-cache-dir/node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", "dev": true, "dependencies": { - "@koa/router": "^9.0.1", - "commander": "^6.0.0", - "fs-extra": "^9.0.1", - "koa": "^2.12.0", - "koa-static": "^5.0.0", - "open": "^7.0.4", - "portfinder": "^1.0.26", - "replace-in-file": "^6.1.0" - }, - "bin": { - "tailwind-config-viewer": "cli/index.js", - "tailwindcss-config-viewer": "cli/index.js" + "find-up": "^4.0.0" }, "engines": { "node": ">=8" - }, - "peerDependencies": { - "tailwindcss": "1 || 2 || 2.0.1-compat || 3" - } - }, - "node_modules/tailwind-config-viewer/node_modules/commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", - "dev": true, - "engines": { - "node": ">= 6" } }, - "node_modules/tailwind-config-viewer/node_modules/open": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", - "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", - "dev": true, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dependencies": { - "is-docker": "^2.0.0", - "is-wsl": "^2.1.1" + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/tailwindcss": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.2.7.tgz", - "integrity": "sha512-B6DLqJzc21x7wntlH/GsZwEXTBttVSl1FtCzC8WP4oBc/NKef7kaax5jeihkkCEWc831/5NDJ9gRNDK6NEioQQ==", - "dev": true, + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", "dependencies": { - "arg": "^5.0.2", - "chokidar": "^3.5.3", - "color-name": "^1.1.4", - "detective": "^5.2.1", - "didyoumean": "^1.2.2", - "dlv": "^1.1.3", - "fast-glob": "^3.2.12", - "glob-parent": "^6.0.2", - "is-glob": "^4.0.3", - "lilconfig": "^2.0.6", - "micromatch": "^4.0.5", - "normalize-path": "^3.0.0", - "object-hash": "^3.0.0", - "picocolors": "^1.0.0", - "postcss": "^8.0.9", - "postcss-import": "^14.1.0", - "postcss-js": "^4.0.0", - "postcss-load-config": "^3.1.4", - "postcss-nested": "6.0.0", - "postcss-selector-parser": "^6.0.11", - "postcss-value-parser": "^4.2.0", - "quick-lru": "^5.1.1", - "resolve": "^1.22.1" - }, - "bin": { - "tailwind": "lib/cli.js", - "tailwindcss": "lib/cli.js" + "flatted": "^3.1.0", + "rimraf": "^3.0.2" }, "engines": { - "node": ">=12.13.0" - }, - "peerDependencies": { - "postcss": "^8.0.9" + "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/tailwindcss/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "node_modules/flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==" }, - "node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "peer": true, + "node_modules/flow-parser": { + "version": "0.227.0", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.227.0.tgz", + "integrity": "sha512-nOygtGKcX/siZK/lFzpfdHEfOkfGcTW7rNroR1Zsz6T/JxSahPALXVt5qVHq/fgvMJuv096BTKbgxN3PzVBaDA==", + "dev": true, "engines": { - "node": ">=6" + "node": ">=0.4.0" } }, - "node_modules/terser": { - "version": "5.16.8", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.8.tgz", - "integrity": "sha512-QI5g1E/ef7d+PsDifb+a6nnVgC4F22Bg6T0xrBrz6iloVB4PUkkunp6V8nzoOOZJIzjWVdAGqCdlKlhLq/TbIA==", - "dependencies": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, + "node_modules/flush-promises": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/flush-promises/-/flush-promises-1.0.2.tgz", + "integrity": "sha512-G0sYfLQERwKz4+4iOZYQEZVpOt9zQrlItIxQAAYAWpfby3gbHrx0osCHz5RLl/XoXevXk0xoN4hDFky/VV9TrA==" + }, + "node_modules/follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], "engines": { - "node": ">=10" + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } } }, - "node_modules/terser-webpack-plugin": { - "version": "5.3.7", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.7.tgz", - "integrity": "sha512-AfKwIktyP7Cu50xNjXF/6Qb5lBNzYaWpU6YfoX3uZicTx0zTy0stDDCsvjDapKsSDvOeWo5MEq4TmdBy2cNoHw==", + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.17", - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.16.5" + "is-callable": "^1.1.3" + } + }, + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" }, "engines": { - "node": ">= 10.13.0" + "node": ">=14" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "uglify-js": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/terser-webpack-plugin/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==", + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "dev": true, "engines": { - "node": ">=8" + "node": "*" } }, - "node_modules/terser-webpack-plugin/node_modules/jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "node_modules/form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" }, "engines": { - "node": ">= 10.13.0" + "node": ">= 0.12" } }, - "node_modules/terser-webpack-plugin/node_modules/schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true, "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "node": ">= 0.6" } }, - "node_modules/terser-webpack-plugin/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==", - "dependencies": { - "has-flag": "^4.0.0" - }, + "node_modules/fraction.js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", + "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==", + "dev": true, "engines": { - "node": ">=10" + "node": "*" }, "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "type": "patreon", + "url": "https://www.patreon.com/infusion" } }, - "node_modules/terser/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" - }, - "node_modules/throttle-debounce": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-3.0.1.tgz", - "integrity": "sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg==", + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "dev": true, "engines": { - "node": ">=10" + "node": ">= 0.6" } }, - "node_modules/throttleit": { + "node_modules/fs-constants": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", - "integrity": "sha512-rkTVqu6IjfQ/6+uNuuc3sZek4CEYxTJom3IktzgdSxcZqdARuebbA/f4QmAxMQIxqq9ZLEUkSYqvuk1I6VKq4g==", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", "dev": true }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true + "node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } }, - "node_modules/tiny-emitter": { + "node_modules/fs-minipass": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", - "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==" - }, - "node_modules/tippy.js": { - "version": "6.3.7", - "resolved": "https://registry.npmjs.org/tippy.js/-/tippy.js-6.3.7.tgz", - "integrity": "sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ==", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, "dependencies": { - "@popperjs/core": "^2.9.0" + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" } }, - "node_modules/tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "dev": true, "dependencies": { - "rimraf": "^3.0.0" + "yallist": "^4.0.0" }, "engines": { - "node": ">=8.17.0" + "node": ">=8" } }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "node_modules/fs-minipass/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=4" + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "devOptional": true, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", "dependencies": { - "is-number": "^7.0.0" + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" }, "engines": { - "node": ">=8.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true, "engines": { - "node": ">=0.6" + "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/toposort": { + "node_modules/get-func-name": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", - "integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==" - }, - "node_modules/tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", + "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-nonce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz", + "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==", + "dev": true, "engines": { - "node": ">=0.8" + "node": ">=6" } }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + "node_modules/get-npm-tarball-url": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/get-npm-tarball-url/-/get-npm-tarball-url-2.1.0.tgz", + "integrity": "sha512-ro+DiMu5DXgRBabqXupW38h7WPZ9+Ad8UjwhvsmmN8w1sU7ab0nzAXvVZ4kqYg57OrqomRtJvepX5/xvFKNtjA==", + "dev": true, + "engines": { + "node": ">=12.17" + } }, - "node_modules/tree-kill": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", - "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", "dev": true, - "bin": { - "tree-kill": "cli.js" + "engines": { + "node": ">=8.0.0" } }, - "node_modules/tsconfig-paths": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", - "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", - "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" + "node_modules/get-port": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz", + "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/tsconfig-paths/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", "dependencies": { - "minimist": "^1.2.0" + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" }, - "bin": { - "json5": "lib/cli.js" + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", - "dev": true + "node_modules/getos": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/getos/-/getos-3.2.1.tgz", + "integrity": "sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q==", + "dev": true, + "dependencies": { + "async": "^3.2.0" + } }, - "node_modules/tsscmp": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz", - "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==", + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", "dev": true, - "engines": { - "node": ">=0.6.x" + "dependencies": { + "assert-plus": "^1.0.0" } }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "node_modules/giget": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/giget/-/giget-1.2.1.tgz", + "integrity": "sha512-4VG22mopWtIeHwogGSy1FViXVo0YT+m6BrqZfz0JJFwbSsePsCdOzdLIIli5BtMp7Xe8f/o2OmBpQX2NBOC24g==", "dev": true, "dependencies": { - "safe-buffer": "^5.0.1" + "citty": "^0.1.5", + "consola": "^3.2.3", + "defu": "^6.1.3", + "node-fetch-native": "^1.6.1", + "nypm": "^0.3.3", + "ohash": "^1.1.3", + "pathe": "^1.1.1", + "tar": "^6.2.0" }, - "engines": { - "node": "*" + "bin": { + "giget": "dist/cli.mjs" } }, - "node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "node_modules/github-slugger": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.5.0.tgz", + "integrity": "sha512-wIh+gKBI9Nshz2o46B0B3f5k/W+WI9ZAv6y5Dn5WJ5SK1t0TnDimB4WE5rmTD05ZAIn8HALCZVmCsvj0w0v0lw==", "dev": true }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "dependencies": { - "prelude-ls": "^1.2.1" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" }, "engines": { - "node": ">= 0.8.0" + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" + }, + "node_modules/global-dirs": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", + "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", "dev": true, + "dependencies": { + "ini": "2.0.0" + }, "engines": { "node": ">=10" }, @@ -11041,913 +12724,845 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dev": true, - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "engines": { - "node": ">= 0.6" + "node": ">=4" } }, - "node_modules/typed-array-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", - "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", "dependencies": { - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/typescript": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", - "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", - "devOptional": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" }, "engines": { - "node": ">=12.20" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/uc.micro": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", - "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==" - }, - "node_modules/ufo": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.1.1.tgz", - "integrity": "sha512-MvlCc4GHrmZdAllBc0iUDowff36Q9Ndw/UzqmEKyrfSzokTd9ZCy1i+IIk5hrYKkjoYVQyNbrw7/F8XJ2rEwTg==", - "dev": true - }, - "node_modules/unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", "dependencies": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" + "get-intrinsic": "^1.1.3" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/unimport": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/unimport/-/unimport-3.0.4.tgz", - "integrity": "sha512-eoof/HLiNJcIkVpnqc7sJbzKSLx39J6xTaP7E4ElgVQKeq2t9fPTkvJKcA55IJTaRPkEkDq8kcc/IZPmrypnFg==", + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "node_modules/grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==" + }, + "node_modules/gunzip-maybe": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/gunzip-maybe/-/gunzip-maybe-1.4.2.tgz", + "integrity": "sha512-4haO1M4mLO91PW57BMsDFf75UmwoRX0GkdD+Faw+Lr+r/OZrOCS0pIBwOL1xCKQqnQzbNFGgK2V2CpBUPeFNTw==", "dev": true, "dependencies": { - "@rollup/pluginutils": "^5.0.2", - "escape-string-regexp": "^5.0.0", - "fast-glob": "^3.2.12", - "local-pkg": "^0.4.3", - "magic-string": "^0.30.0", - "mlly": "^1.2.0", - "pathe": "^1.1.0", - "pkg-types": "^1.0.2", - "scule": "^1.0.0", - "strip-literal": "^1.0.1", - "unplugin": "^1.3.1" + "browserify-zlib": "^0.1.4", + "is-deflate": "^1.0.0", + "is-gzip": "^1.0.0", + "peek-stream": "^1.1.0", + "pumpify": "^1.3.3", + "through2": "^2.0.3" + }, + "bin": { + "gunzip-maybe": "bin.js" } }, - "node_modules/unimport/node_modules/escape-string-regexp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", - "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "node_modules/handlebars": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", "dev": true, - "engines": { - "node": ">=12" + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/universal-user-agent": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", - "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" - }, - "node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true, "engines": { - "node": ">= 10.0.0" + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" } }, - "node_modules/unleash-proxy-client": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/unleash-proxy-client/-/unleash-proxy-client-2.4.3.tgz", - "integrity": "sha512-ILJIHNSeh7ajHczemNE19Rl3NpVU3voFouYIgWCbJd+OhuJ9elfpuD1LF5yucEJq8AuWKkEM2AzUFFOTiv/2Sw==", + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dependencies": { - "tiny-emitter": "^2.1.0", - "uuid": "^8.3.2" + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" } }, - "node_modules/unleash-proxy-client/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "bin": { - "uuid": "dist/bin/uuid" + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/unplugin": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.3.1.tgz", - "integrity": "sha512-h4uUTIvFBQRxUKS2Wjys6ivoeofGhxzTe2sRWlooyjHXVttcVfV/JiavNd3d4+jty0SVV0dxGw9AkY9MwiaCEw==", - "dev": true, - "dependencies": { - "acorn": "^8.8.2", - "chokidar": "^3.5.3", - "webpack-sources": "^3.2.3", - "webpack-virtual-modules": "^0.5.0" + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" } }, - "node_modules/unplugin-auto-import": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/unplugin-auto-import/-/unplugin-auto-import-0.15.2.tgz", - "integrity": "sha512-Wivfu+xccgvEZG8QtZcIvt6napfX9wyOFqM//7FHOtev8+k+dp3ykiqsEl6TODgHmqTTBeQX4Ah1JvRgUNjlkg==", - "dev": true, + "node_modules/has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", "dependencies": { - "@antfu/utils": "^0.7.2", - "@rollup/pluginutils": "^5.0.2", - "local-pkg": "^0.4.3", - "magic-string": "^0.30.0", - "minimatch": "^7.4.3", - "unimport": "^3.0.3", - "unplugin": "^1.3.1" + "get-intrinsic": "^1.1.1" }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", "engines": { - "node": ">=14" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/antfu" - }, - "peerDependencies": { - "@nuxt/kit": "^3.2.2", - "@vueuse/core": "*" - }, - "peerDependenciesMeta": { - "@nuxt/kit": { - "optional": true - }, - "@vueuse/core": { - "optional": true - } + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/unplugin-auto-import/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/unplugin-auto-import/node_modules/minimatch": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.3.tgz", - "integrity": "sha512-5UB4yYusDtkRPbRiy1cqZ1IpGNcJCGlEMG17RKzPddpyiPKoCdwohbED8g4QXT0ewCt8LTkQXuljsUfQ3FKM4A==", - "dev": true, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", "dependencies": { - "brace-expansion": "^2.0.1" + "has-symbols": "^1.0.2" }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/unplugin-vue-components": { - "version": "0.24.1", - "resolved": "https://registry.npmjs.org/unplugin-vue-components/-/unplugin-vue-components-0.24.1.tgz", - "integrity": "sha512-T3A8HkZoIE1Cja95xNqolwza0yD5IVlgZZ1PVAGvVCx8xthmjsv38xWRCtHtwl+rvZyL9uif42SRkDGw9aCfMA==", + "node_modules/hash-sum": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-2.0.0.tgz", + "integrity": "sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==" + }, + "node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "node_modules/http-assert": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/http-assert/-/http-assert-1.5.0.tgz", + "integrity": "sha512-uPpH7OKX4H25hBmU6G1jWNaqJGpTXxey+YOUizJUAgu0AjLUeC8D73hTrhvDS5D+GJN1DN1+hhc/eF/wpxtp0w==", "dev": true, "dependencies": { - "@antfu/utils": "^0.7.2", - "@rollup/pluginutils": "^5.0.2", - "chokidar": "^3.5.3", - "debug": "^4.3.4", - "fast-glob": "^3.2.12", - "local-pkg": "^0.4.3", - "magic-string": "^0.30.0", - "minimatch": "^7.4.2", - "resolve": "^1.22.1", - "unplugin": "^1.1.0" + "deep-equal": "~1.0.1", + "http-errors": "~1.8.0" }, "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - }, - "peerDependencies": { - "@babel/parser": "^7.15.8", - "@nuxt/kit": "^3.2.2", - "vue": "2 || 3" - }, - "peerDependenciesMeta": { - "@babel/parser": { - "optional": true - }, - "@nuxt/kit": { - "optional": true - } + "node": ">= 0.8" } }, - "node_modules/unplugin-vue-components/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "node_modules/http-assert/node_modules/deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha512-bHtC0iYvWhyaTzvV3CZgPeZQqCOBGyGsVV7v4eevpdkLHfiSrXUdBG+qAuSz4RI70sszvjQ1QSZ98An1yNwpSw==", + "dev": true + }, + "node_modules/http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", "dev": true, "dependencies": { - "balanced-match": "^1.0.0" + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.6" } }, - "node_modules/unplugin-vue-components/node_modules/minimatch": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.3.tgz", - "integrity": "sha512-5UB4yYusDtkRPbRiy1cqZ1IpGNcJCGlEMG17RKzPddpyiPKoCdwohbED8g4QXT0ewCt8LTkQXuljsUfQ3FKM4A==", + "node_modules/http-signature": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.3.6.tgz", + "integrity": "sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==", "dev": true, "dependencies": { - "brace-expansion": "^2.0.1" + "assert-plus": "^1.0.0", + "jsprim": "^2.0.2", + "sshpk": "^1.14.1" }, "engines": { - "node": ">=10" + "node": ">=0.10" + } + }, + "node_modules/https-proxy-agent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz", + "integrity": "sha512-zoDhWrkR3of1l9QAL8/scJZyLu8j/gBkcwcaQOZh7Gyh/+uJQzGVETdgT30akuwkpL8HTRfssqI3BZuV18teDg==", + "dev": true, + "dependencies": { + "agent-base": "5", + "debug": "4" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "engines": { + "node": ">= 6.0.0" } }, - "node_modules/unplugin/node_modules/webpack-virtual-modules": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.5.0.tgz", - "integrity": "sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==", - "dev": true + "node_modules/human-signals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", + "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", + "dev": true, + "engines": { + "node": ">=8.12.0" + } }, - "node_modules/untildify": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", - "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/update-browserslist-db": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", - "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, "funding": [ { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" + "type": "github", + "url": "https://github.com/sponsors/feross" }, { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" } - ], + ] + }, + "node_modules/ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/immutable": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.0.tgz", + "integrity": "sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg==", + "devOptional": true + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" }, - "bin": { - "browserslist-lint": "cli.js" + "engines": { + "node": ">=6" }, - "peerDependencies": { - "browserslist": ">= 4.21.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dependencies": { - "punycode": "^2.1.0" + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "engines": { + "node": ">=0.8.19" } }, - "node_modules/url-search-params-polyfill": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/url-search-params-polyfill/-/url-search-params-polyfill-7.0.1.tgz", - "integrity": "sha512-bAw7L2E+jn9XHG5P9zrPnHdO0yJub4U+yXJOdpcpkr7OBd9T8oll4lUos0iSGRcDvfZoLUKfx9a6aNmIhJ4+mQ==" - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - }, - "node_modules/uuid": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.0.tgz", - "integrity": "sha512-fX6Z5o4m6XsXBdli9g7DtWgAx+osMsRRZFKma1mIUsLCz6vRvv+pz5VNbyu9UEDzpMWulZfvpgb/cmDXVulYFQ==", - "bin": { - "uuid": "dist/bin/uuid" + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" } }, - "node_modules/v-network-graph": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/v-network-graph/-/v-network-graph-0.8.2.tgz", - "integrity": "sha512-JmuP07z1+/nmZs/6/2x0IU978VrikcOC5ZsC8H9+jEZUzqoEftYfenQRRncGU6YQWAdj0uMxFMb+acYLGYyxog==", + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "dependencies": { - "@dash14/svg-pan-zoom": "^3.6.9", - "mitt": "^3.0.0" - }, - "peerDependencies": { - "d3-force": "^3.0.0", - "vue": "^3.2.45" + "once": "^1.3.0", + "wrappy": "1" } }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "dev": true, - "engines": { - "node": ">= 0.8" - } + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, - "node_modules/verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "node_modules/ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", "dev": true, - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" + "engines": { + "node": ">=10" } }, - "node_modules/vite": { - "version": "4.4.7", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.4.7.tgz", - "integrity": "sha512-6pYf9QJ1mHylfVh39HpuSfMPojPSKVxZvnclX1K1FyZ1PXDOcLBibdq5t1qxJSnL63ca8Wf4zts6mD8u8oc9Fw==", + "node_modules/internal-slot": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", + "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", "dependencies": { - "esbuild": "^0.18.10", - "postcss": "^8.4.26", - "rollup": "^3.25.2" - }, - "bin": { - "vite": "bin/vite.js" + "get-intrinsic": "^1.2.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" }, "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - }, - "peerDependencies": { - "@types/node": ">= 14", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } + "node": ">= 0.4" } }, - "node_modules/vue": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.3.1.tgz", - "integrity": "sha512-3Rwy4I5idbPVSDZu6I+fFh6tdDSZbauImCTqLxE7y0LpHtiDvPeY01OI7RkFPbva1nk4hoO0sv/NzosH2h60sg==", + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, "dependencies": { - "@vue/compiler-dom": "3.3.1", - "@vue/compiler-sfc": "3.3.1", - "@vue/runtime-dom": "3.3.1", - "@vue/server-renderer": "3.3.1", - "@vue/shared": "3.3.1" + "loose-envify": "^1.0.0" } }, - "node_modules/vue-3-sanitize": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/vue-3-sanitize/-/vue-3-sanitize-0.1.4.tgz", - "integrity": "sha512-8+iU+MC94ibyOBUpn4g2hk8Dy32M7PKIi3UoUG+6Pd47J/uHIDdOdeXEEmCM/rVdyFqNXqLfO+yZT2BesGNlXA==", - "dependencies": { - "sanitize-html": "^2.0.0" + "node_modules/ip": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", + "dev": true + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true, + "engines": { + "node": ">= 0.10" } }, - "node_modules/vue-draggable-next": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/vue-draggable-next/-/vue-draggable-next-2.2.1.tgz", - "integrity": "sha512-EAMS1IRHF0kZO0o5PMOinsQsXIqsrKT1hKmbICxG3UEtn7zLFkLxlAtajcCcUTisNvQ6TtCB5COjD9a1raNADw==", - "peerDependencies": { - "sortablejs": "^1.14.0", - "vue": "^3.2.2" + "node_modules/is-absolute-url": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz", + "integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==", + "dev": true, + "engines": { + "node": ">=8" } }, - "node_modules/vue-eslint-parser": { - "version": "9.2.1", - "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.2.1.tgz", - "integrity": "sha512-tPOex4n6jit4E7h68auOEbDMwE58XiP4dylfaVTCOVCouR45g+QFDBjgIdEU52EXJxKyjgh91dLfN2rxUcV0bQ==", + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", "dependencies": { - "debug": "^4.3.4", - "eslint-scope": "^7.1.1", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.3.1", - "esquery": "^1.4.0", - "lodash": "^4.17.21", - "semver": "^7.3.6" + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" }, "engines": { - "node": "^14.17.0 || >=16.0.0" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=6.0.0" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/vue-eslint-parser/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/is-array-buffer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", "dependencies": { - "yallist": "^4.0.0" + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" }, - "engines": { - "node": ">=10" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/vue-eslint-parser/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", "dependencies": { - "lru-cache": "^6.0.0" + "has-bigints": "^1.0.1" }, - "bin": { - "semver": "bin/semver.js" + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "devOptional": true, + "dependencies": { + "binary-extensions": "^2.0.0" }, "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/vue-eslint-parser/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/vue-grid-layout": { - "version": "3.0.0-beta1", - "resolved": "https://registry.npmjs.org/vue-grid-layout/-/vue-grid-layout-3.0.0-beta1.tgz", - "integrity": "sha512-MsW0yfYNtnAO/uDhfZvkP6effxSJxvhAFbIL37x6Rn3vW9xf0WHVefKaSbQMLpSq3mXnR6ut0pg2Cd5lqIIZzg==", + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", "dependencies": { - "@interactjs/actions": "^1.10.2", - "@interactjs/auto-start": "^1.10.2", - "@interactjs/dev-tools": "^1.10.2", - "@interactjs/interactjs": "^1.10.2", - "@interactjs/modifiers": "^1.10.2", - "element-resize-detector": "^1.2.1", - "mitt": "^2.1.0" + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/vue-grid-layout/node_modules/mitt": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mitt/-/mitt-2.1.0.tgz", - "integrity": "sha512-ILj2TpLiysu2wkBbWjAmww7TkZb65aiQO+DkVdUTBpBXq+MHYiETENkKFMtsJZX1Lf4pe4QOrTSjIfUwN5lRdg==" - }, - "node_modules/vue-json-pretty": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/vue-json-pretty/-/vue-json-pretty-2.2.4.tgz", - "integrity": "sha512-JX80b3QDrspcH43C53CdtYeq/froApQGSV5y43bEMWFj2LGOxB96aH1VmvrFA21nD1WTP6nwfFMQqGXuS4jyFQ==", + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", "engines": { - "node": ">= 10.0.0", - "npm": ">= 5.0.0" + "node": ">= 0.4" }, - "peerDependencies": { - "vue": ">=3.0.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/vue-loader": { - "version": "16.8.3", - "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.8.3.tgz", - "integrity": "sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA==", + "node_modules/is-ci": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", + "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", + "dev": true, "dependencies": { - "chalk": "^4.1.0", - "hash-sum": "^2.0.0", - "loader-utils": "^2.0.0" + "ci-info": "^3.2.0" }, - "peerDependencies": { - "webpack": "^4.1.0 || ^5.0.0-0" + "bin": { + "is-ci": "bin.js" } }, - "node_modules/vue-loader/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/is-core-module": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", + "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" + "has": "^1.0.3" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/vue-loader/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "has-tostringtag": "^1.0.0" }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/vue-loader/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" + "node_modules/is-deflate": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-deflate/-/is-deflate-1.0.0.tgz", + "integrity": "sha512-YDoFpuZWu1VRXlsnlYMzKyVRITXj7Ej/V9gXQ2/pAe7X1J7M/RNOqaIYi6qUn+B7nGyB9pDXrv02dsB58d2ZAQ==", + "dev": true + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true, + "bin": { + "is-docker": "cli.js" }, "engines": { - "node": ">=7.0.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/vue-loader/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/vue-loader/node_modules/has-flag": { + "node_modules/is-expression": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "engines": { - "node": ">=8" + "resolved": "https://registry.npmjs.org/is-expression/-/is-expression-4.0.0.tgz", + "integrity": "sha512-zMIXX63sxzG3XrkHkrAPvm/OVZVSCPNkwMHU8oTX7/U3AL78I0QXCEICXUM13BIa8TYGZ68PiTKfQz3yaTNr4A==", + "dev": true, + "dependencies": { + "acorn": "^7.1.1", + "object-assign": "^4.1.1" } }, - "node_modules/vue-loader/node_modules/loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" + "node_modules/is-expression/node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" }, "engines": { - "node": ">=8.9.0" + "node": ">=0.4.0" } }, - "node_modules/vue-loader/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", "dependencies": { - "has-flag": "^4.0.0" + "is-plain-object": "^2.0.4" }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/vue-router": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.1.6.tgz", - "integrity": "sha512-DYWYwsG6xNPmLq/FmZn8Ip+qrhFEzA14EI12MsMgVxvHFDYvlr4NXpVF5hrRH1wVcDP8fGi5F4rxuJSl8/r+EQ==", + "node_modules/is-extendable/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "dependencies": { - "@vue/devtools-api": "^6.4.5" - }, - "funding": { - "url": "https://github.com/sponsors/posva" + "isobject": "^3.0.1" }, - "peerDependencies": { - "vue": "^3.2.0" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/vue3-click-away": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/vue3-click-away/-/vue3-click-away-1.2.4.tgz", - "integrity": "sha512-O9Z2KlvIhJT8OxaFy04eiZE9rc1Mk/bp+70dLok68ko3Kr8AW5dU+j8avSk4GDQu94FllSr4m5ul4BpzlKOw1A==" + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/vue3-lazyload": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/vue3-lazyload/-/vue3-lazyload-0.3.6.tgz", - "integrity": "sha512-UcVnEN9JzxeFBa7nNAPWKXHTtvVAzWYhBSvRU+Gmx9MdTGLWKwjZiNSyB1Os25jr9HaFHWY0DaU8uugXkGu9Gw==", + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dev": true, "dependencies": { - "vue-demi": "^0.12.5" + "has-tostringtag": "^1.0.0" }, - "peerDependencies": { - "@vue/composition-api": "^1.0.0-rc.1", - "vue": "^2.0.0 || >=3.0.0" + "engines": { + "node": ">= 0.4" }, - "peerDependenciesMeta": { - "@vue/composition-api": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/vue3-lazyload/node_modules/vue-demi": { - "version": "0.12.5", - "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.12.5.tgz", - "integrity": "sha512-BREuTgTYlUr0zw0EZn3hnhC3I6gPWv+Kwh4MCih6QcAeaTlaIX0DwOVN0wHej7hSvDPecz4jygy/idsgKfW58Q==", - "hasInstallScript": true, - "bin": { - "vue-demi-fix": "bin/vue-demi-fix.js", - "vue-demi-switch": "bin/vue-demi-switch.js" + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - }, - "peerDependencies": { - "@vue/composition-api": "^1.0.0-rc.1", - "vue": "^3.0.0-0 || ^2.6.0" - }, - "peerDependenciesMeta": { - "@vue/composition-api": { - "optional": true - } + "node": ">=0.10.0" } }, - "node_modules/vuedraggable": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/vuedraggable/-/vuedraggable-4.1.0.tgz", - "integrity": "sha512-FU5HCWBmsf20GpP3eudURW3WdWTKIbEIQxh9/8GE806hydR9qZqRRxRE3RjqX7PkuLuMQG/A7n3cfj9rCEchww==", - "dependencies": { - "sortablejs": "1.14.0" - }, - "peerDependencies": { - "vue": "^3.0.1" + "node_modules/is-gzip": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-gzip/-/is-gzip-1.0.0.tgz", + "integrity": "sha512-rcfALRIb1YewtnksfRIHGcIY93QnK8BIQ/2c9yDYcG/Y6+vRoJuTWBmmSEbyLLYtXm7q35pHOHbZFQBaLrhlWQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/vuex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/vuex/-/vuex-4.1.0.tgz", - "integrity": "sha512-hmV6UerDrPcgbSy9ORAtNXDr9M4wlNP4pEFKye4ujJF8oqgFFuxDCdOLS3eNoRTtq5O3hoBDh9Doj1bQMYHRbQ==", + "node_modules/is-installed-globally": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", + "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", + "dev": true, "dependencies": { - "@vue/devtools-api": "^6.0.0-beta.11" + "global-dirs": "^3.0.0", + "is-path-inside": "^3.0.2" }, - "peerDependencies": { - "vue": "^3.2.0" + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/w3c-keyname": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.6.tgz", - "integrity": "sha512-f+fciywl1SJEniZHD6H+kUO8gOnwIr7f4ijKA6+ZvJFjeGi1r4PDLl53Ayud9O/rk64RqgoQine0feoeOU0kXg==" - }, - "node_modules/wait-on": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-6.0.1.tgz", - "integrity": "sha512-zht+KASY3usTY5u2LgaNqn/Cd8MukxLGjdcZxT2ns5QzDmTFc4XoWBgC+C/na+sMRZTuVygQoMYwdcVjHnYIVw==", + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", "dev": true, - "dependencies": { - "axios": "^0.25.0", - "joi": "^17.6.0", - "lodash": "^4.17.21", - "minimist": "^1.2.5", - "rxjs": "^7.5.4" - }, - "bin": { - "wait-on": "bin/wait-on" - }, "engines": { - "node": ">=10.0.0" + "node": ">=8" } }, - "node_modules/wait-on/node_modules/axios": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.25.0.tgz", - "integrity": "sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g==", - "dev": true, - "dependencies": { - "follow-redirects": "^1.14.7" + "node_modules/is-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", + "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/watchpack": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", - "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", - "peer": true, + "node_modules/is-nan": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", + "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", + "dev": true, "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" }, "engines": { - "node": ">=10.13.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "node_modules/webpack": { - "version": "5.82.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.82.1.tgz", - "integrity": "sha512-C6uiGQJ+Gt4RyHXXYt+v9f+SN1v83x68URwgxNQ98cvH8kxiuywWGP4XeNZ1paOzZ63aY3cTciCEQJNFUljlLw==", - "peer": true, - "dependencies": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^1.0.0", - "@webassemblyjs/ast": "^1.11.5", - "@webassemblyjs/wasm-edit": "^1.11.5", - "@webassemblyjs/wasm-parser": "^1.11.5", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.7.6", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.14.0", - "es-module-lexer": "^1.2.1", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.1.2", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.7", - "watchpack": "^2.4.0", - "webpack-sources": "^3.2.3" - }, - "bin": { - "webpack": "bin/webpack.js" - }, + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", "engines": { - "node": ">=10.13.0" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "devOptional": true, "engines": { - "node": ">=10.13.0" + "node": ">=0.12.0" } }, - "node_modules/webpack/node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "peer": true, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" + "has-tostringtag": "^1.0.0" }, "engines": { - "node": ">=8.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/webpack/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "peer": true, + "node_modules/is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", + "dev": true, "engines": { - "node": ">=4.0" + "node": ">=6" } }, - "node_modules/webpack/node_modules/schema-utils": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.2.tgz", - "integrity": "sha512-pvjEHOgWc9OWA/f/DE3ohBWTD6EleVLf7iFUkoSwAxttdBhB9QUebQgxER2kWueOvRJXPHNnyrvvh9eZINB8Eg==", - "peer": true, - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "node": ">=8" } }, - "node_modules/whatwg-url": { + "node_modules/is-plain-object": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "engines": { + "node": ">=0.10.0" } }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "node_modules/is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", + "dev": true + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" }, "engines": { - "node": ">= 8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - }, + "node_modules/is-set": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", + "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/which-collection": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", - "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", + "node_modules/is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", "dependencies": { - "is-map": "^2.0.1", - "is-set": "^2.0.1", - "is-weakmap": "^2.0.1", - "is-weakset": "^2.0.1" + "call-bind": "^1.0.2" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/which-typed-array": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", - "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", + "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", "dependencies": { "available-typed-arrays": "^1.0.5", "call-bind": "^1.0.2", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.10" + "has-tostringtag": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -11956,32 +13571,153 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "dev": true + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", + "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", + "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", "engines": { "node": ">=0.10.0" } }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", + "dev": true + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", "dev": true, "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" }, "engines": { - "node": ">=10" + "node": ">=8" + } + }, + "node_modules/jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" }, "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" } }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { + "node_modules/jake": { + "version": "10.8.7", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.7.tgz", + "integrity": "sha512-ZDi3aP+fG/LchyBzUM804VjddnwfSfsdeYkwt8NcbKRvo4rFkjhs456iLFn3k2ZUWvNe4i48WACDbza8fhq2+w==", + "dev": true, + "dependencies": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.4", + "minimatch": "^3.1.2" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jake/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", @@ -11996,7 +13732,23 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/wrap-ansi/node_modules/color-convert": { + "node_modules/jake/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jake/node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", @@ -12008,935 +13760,11405 @@ "node": ">=7.0.0" } }, - "node_modules/wrap-ansi/node_modules/color-name": { + "node_modules/jake/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - }, - "node_modules/ws": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", - "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/xml-name-validator": { + "node_modules/jake/node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", - "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", - "engines": { - "node": ">=12" - } - }, - "node_modules/xmlhttprequest-ssl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz", - "integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "engines": { - "node": ">=0.4.0" + "node": ">=8" } }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "node_modules/jake/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { - "node": ">=0.4" + "node": ">=8" } }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" - }, - "node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + }, "engines": { - "node": ">= 6" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" } }, - "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "node_modules/jest-mock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", + "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", "dev": true, "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" + "@jest/types": "^27.5.1", + "@types/node": "*" }, "engines": { - "node": ">=12" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "node_modules/jest-mock/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, "engines": { - "node": ">=12" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "node_modules/jest-mock/node_modules/@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", "dev": true, "dependencies": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" + "@types/yargs-parser": "*" } }, - "node_modules/ylru": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/ylru/-/ylru-1.3.2.tgz", - "integrity": "sha512-RXRJzMiK6U2ye0BlGGZnmpwJDPgakn6aNQ0A7gHRbD4I0uvK4TW6UqkK1V0pp9jskjJBAXd3dRrbzWkqJ+6cxA==", + "node_modules/jest-mock/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">= 4.0.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "node_modules/jest-mock/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/yup": { - "version": "0.32.11", - "resolved": "https://registry.npmjs.org/yup/-/yup-0.32.11.tgz", - "integrity": "sha512-Z2Fe1bn+eLstG8DRR6FTavGD+MeAwyfmouhHsIUgaADz8jvFKbO/fXc2trJKZg+5EBjh4gGm3iU/t3onKlXHIg==", + "node_modules/jest-mock/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { - "@babel/runtime": "^7.15.4", - "@types/lodash": "^4.14.175", - "lodash": "^4.17.21", - "lodash-es": "^4.17.21", - "nanoclone": "^0.2.1", - "property-expr": "^2.0.4", - "toposort": "^2.0.2" + "color-name": "~1.1.4" }, "engines": { - "node": ">=10" - } - } - }, - "dependencies": { - "@ampproject/remapping": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", - "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", - "requires": { - "@jridgewell/gen-mapping": "^0.1.0", - "@jridgewell/trace-mapping": "^0.3.9" + "node": ">=7.0.0" } }, - "@antfu/utils": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/@antfu/utils/-/utils-0.7.2.tgz", - "integrity": "sha512-vy9fM3pIxZmX07dL+VX1aZe7ynZ+YyB0jY+jE6r3hOK6GNY2t6W8rzpFC4tgpbXUYABkFQwgJq2XYXlxbXAI0g==", + "node_modules/jest-mock/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", - "requires": { - "@babel/highlight": "^7.18.6" - } - }, - "@babel/compat-data": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.0.tgz", - "integrity": "sha512-gMuZsmsgxk/ENC3O/fRw5QY8A9/uxQbbCEypnLIiYYc/qVJtEV7ouxC3EllIIwNzMqAQee5tanFabWsUOutS7g==" - }, - "@babel/core": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.3.tgz", - "integrity": "sha512-qIJONzoa/qiHghnm0l1n4i/6IIziDpzqc36FBs4pzMhDUraHqponwJLiAKm1hGLP3OSB/TVNz6rMwVGpwxxySw==", - "requires": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.21.3", - "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-module-transforms": "^7.21.2", - "@babel/helpers": "^7.21.0", - "@babel/parser": "^7.21.3", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.3", - "@babel/types": "^7.21.3", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.2", - "semver": "^6.3.0" + "node_modules/jest-mock/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" } }, - "@babel/generator": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.3.tgz", - "integrity": "sha512-QS3iR1GYC/YGUnW7IdggFeN5c1poPUurnGttOV/bZgPGV+izC/D8HnD6DLwod0fsatNyVn1G3EVWMYIF0nHbeA==", - "requires": { - "@babel/types": "^7.21.3", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" - }, + "node_modules/jest-mock/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { - "@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "requires": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - } - } + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "@babel/helper-compilation-targets": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz", - "integrity": "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==", - "requires": { - "@babel/compat-data": "^7.20.5", - "@babel/helper-validator-option": "^7.18.6", - "browserslist": "^4.21.3", - "lru-cache": "^5.1.1", - "semver": "^6.3.0" + "node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "@babel/helper-environment-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", - "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==" - }, - "@babel/helper-function-name": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz", - "integrity": "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==", - "requires": { - "@babel/template": "^7.20.7", - "@babel/types": "^7.21.0" + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "@babel/helper-hoist-variables": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", - "requires": { - "@babel/types": "^7.18.6" + "node_modules/jest-util/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "@babel/helper-module-imports": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", - "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", - "requires": { - "@babel/types": "^7.18.6" + "node_modules/jest-util/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "@babel/helper-module-transforms": { - "version": "7.21.2", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz", - "integrity": "sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==", - "requires": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-simple-access": "^7.20.2", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/helper-validator-identifier": "^7.19.1", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.2", - "@babel/types": "^7.21.2" + "node_modules/jest-util/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "@babel/helper-plugin-utils": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz", - "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==" - }, - "@babel/helper-simple-access": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", - "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", - "requires": { - "@babel/types": "^7.20.2" - } + "node_modules/jest-util/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, - "@babel/helper-split-export-declaration": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", - "requires": { - "@babel/types": "^7.18.6" + "node_modules/jest-util/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" } }, - "@babel/helper-string-parser": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", - "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==" - }, - "@babel/helper-validator-identifier": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==" - }, - "@babel/helper-validator-option": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz", - "integrity": "sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==" - }, - "@babel/helpers": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.0.tgz", - "integrity": "sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA==", - "requires": { - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.0", - "@babel/types": "^7.21.0" - } - }, - "@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", - "requires": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" + "node_modules/jest-util/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "@babel/parser": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.3.tgz", - "integrity": "sha512-lobG0d7aOfQRXh8AyklEAgZGvA4FShxo6xQbUrrT/cNBPUdIDojlokwJsQyCC/eKia7ifqM0yP+2DRZ4WKw2RQ==" - }, - "@babel/plugin-proposal-export-namespace-from": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz", - "integrity": "sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==", - "requires": { - "@babel/helper-plugin-utils": "^7.18.9", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + "node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "@babel/plugin-syntax-dynamic-import": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", - "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" + "node_modules/jest-worker/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" } }, - "@babel/plugin-syntax-export-namespace-from": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", - "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", - "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "node_modules/jest-worker/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" } }, - "@babel/plugin-transform-modules-commonjs": { - "version": "7.21.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.21.2.tgz", - "integrity": "sha512-Cln+Yy04Gxua7iPdj6nOV96smLGjpElir5YwzF0LBPKoPlLDNJePNlrGGaybAJkd0zKRnOVXOgizSqPYMNYkzA==", - "requires": { - "@babel/helper-module-transforms": "^7.21.2", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-simple-access": "^7.20.2" + "node_modules/joi": { + "version": "17.9.1", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.9.1.tgz", + "integrity": "sha512-FariIi9j6QODKATGBrEX7HZcja8Bsh3rfdGYy/Sb65sGlZWK/QWesU1ghk7aJWDj95knjXlQfSmzFSPPkLVsfw==", + "dev": true, + "dependencies": { + "@hapi/hoek": "^9.0.0", + "@hapi/topo": "^5.0.0", + "@sideway/address": "^4.1.3", + "@sideway/formula": "^3.0.1", + "@sideway/pinpoint": "^2.0.0" } }, - "@babel/runtime": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz", - "integrity": "sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==", - "requires": { - "regenerator-runtime": "^0.13.11" + "node_modules/js-sdsl": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.4.0.tgz", + "integrity": "sha512-FfVSdx6pJ41Oa+CF7RDaFmTnCaFhua+SNYQX74riGOpl96x+2jQCqEfQ2bnXu/5DPCqlRuiqyvTJM0Qjz26IVg==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" } }, - "@babel/template": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", - "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", - "requires": { - "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7" - } + "node_modules/js-stringify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/js-stringify/-/js-stringify-1.0.2.tgz", + "integrity": "sha512-rtS5ATOo2Q5k1G+DADISilDA6lv79zIiwFd6CcjuIxGKLFm5C+RLImRscVap9k55i+MOZwgliw+NejvkLuGD5g==", + "dev": true }, - "@babel/traverse": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.3.tgz", - "integrity": "sha512-XLyopNeaTancVitYZe2MlUEvgKb6YVVPXzofHgqHijCImG33b/uTurMS488ht/Hbsb2XK3U2BnSTxKVNGV3nGQ==", - "requires": { - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.21.3", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.21.0", - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.21.3", - "@babel/types": "^7.21.3", - "debug": "^4.1.0", - "globals": "^11.1.0" - } + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, - "@babel/types": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.3.tgz", - "integrity": "sha512-sBGdETxC+/M4o/zKC0sl6sjWv62WFR/uzxrJ6uYyMLZOUlPnwzw0tKgVHOXxaAd5l2g8pEDM5RZ495GPQI77kg==", - "requires": { - "@babel/helper-string-parser": "^7.19.4", - "@babel/helper-validator-identifier": "^7.19.1", - "to-fast-properties": "^2.0.0" + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "@colors/colors": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", - "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", - "dev": true, - "optional": true - }, - "@ctrl/tinycolor": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.0.tgz", - "integrity": "sha512-/Z3l6pXthq0JvMYdUFyX9j0MaCltlIn6mfh9jLyQwg5aPKxkyNa0PTHtU1AlFXLNk55ZuAeJRcpvq+tmLfKmaQ==" + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", + "dev": true }, - "@cubejs-client/core": { - "version": "0.31.63", - "resolved": "https://registry.npmjs.org/@cubejs-client/core/-/core-0.31.63.tgz", - "integrity": "sha512-NFlceV9G2HbFxGqTIjAqS43szRwEJDVzcfuWm/xwlAT6fU4OvZKdDXieKhaxLl38fh64m4VZefej0Mh5jwCmzQ==", - "requires": { - "@babel/runtime": "^7.1.2", - "core-js": "^3.6.5", - "cross-fetch": "^3.0.2", - "dayjs": "^1.10.4", - "ramda": "^0.27.2", - "url-search-params-polyfill": "^7.0.0", - "uuid": "^8.3.2" + "node_modules/jscodeshift": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.15.1.tgz", + "integrity": "sha512-hIJfxUy8Rt4HkJn/zZPU9ChKfKZM1342waJ1QC2e2YsPcWhM+3BJ4dcfQCzArTrk1jJeNLB341H+qOcEHRxJZg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.23.0", + "@babel/parser": "^7.23.0", + "@babel/plugin-transform-class-properties": "^7.22.5", + "@babel/plugin-transform-modules-commonjs": "^7.23.0", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.22.11", + "@babel/plugin-transform-optional-chaining": "^7.23.0", + "@babel/plugin-transform-private-methods": "^7.22.5", + "@babel/preset-flow": "^7.22.15", + "@babel/preset-typescript": "^7.23.0", + "@babel/register": "^7.22.15", + "babel-core": "^7.0.0-bridge.0", + "chalk": "^4.1.2", + "flow-parser": "0.*", + "graceful-fs": "^4.2.4", + "micromatch": "^4.0.4", + "neo-async": "^2.5.0", + "node-dir": "^0.1.17", + "recast": "^0.23.3", + "temp": "^0.8.4", + "write-file-atomic": "^2.3.0" }, - "dependencies": { - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" + "bin": { + "jscodeshift": "bin/jscodeshift.js" + }, + "peerDependencies": { + "@babel/preset-env": "^7.1.6" + }, + "peerDependenciesMeta": { + "@babel/preset-env": { + "optional": true } } }, - "@cubejs-client/vue3": { - "version": "0.31.63", - "resolved": "https://registry.npmjs.org/@cubejs-client/vue3/-/vue3-0.31.63.tgz", - "integrity": "sha512-3s2AHzavz6wudNVW7fhBtRsj0LpF6AoBRCzWm0eefMYHqxYK2ShbVEhz+c2oCM8Fri9vt7ZZt4X+70V5iPJTWw==", - "requires": { - "@cubejs-client/core": "^0.31.63", - "@vue/compiler-sfc": "^3.0.11", - "core-js": "^3.6.5", - "flush-promises": "^1.0.2", - "ramda": "^0.27.0", - "vue-loader": "^16.2.0" + "node_modules/jscodeshift/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "@cypress/request": { - "version": "2.88.11", - "resolved": "https://registry.npmjs.org/@cypress/request/-/request-2.88.11.tgz", - "integrity": "sha512-M83/wfQ1EkspjkE2lNWNV5ui2Cv7UCv1swW1DqljahbzLVWltcsexQh8jYtuS/vzFXP+HySntGM83ZXA9fn17w==", + "node_modules/jscodeshift/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "http-signature": "~1.3.6", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "performance-now": "^2.1.0", - "qs": "~6.10.3", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^8.3.2" - }, "dependencies": { - "qs": { - "version": "6.10.4", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.4.tgz", - "integrity": "sha512-OQiU+C+Ds5qiH91qh/mg0w+8nwQuLjM4F4M/PbmhDOoYehPh+Fb0bDjtR1sOvy7YKxvj28Y/M0PhP5uVX0kB+g==", - "dev": true, - "requires": { - "side-channel": "^1.0.4" - } - }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true - } + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "@cypress/xvfb": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@cypress/xvfb/-/xvfb-1.2.4.tgz", - "integrity": "sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==", + "node_modules/jscodeshift/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, - "requires": { - "debug": "^3.1.0", - "lodash.once": "^4.1.1" - }, "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "@dash14/svg-pan-zoom": { - "version": "3.6.9", - "resolved": "https://registry.npmjs.org/@dash14/svg-pan-zoom/-/svg-pan-zoom-3.6.9.tgz", - "integrity": "sha512-6u+KTQec+9+3bRdk2mReix8AGsp2mB40cw0iYfQQzo22QBkeCNpXl2amnfwQzK7xB9oH/62Wvf2z7l6l2w+csA==" - }, - "@element-plus/icons-vue": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@element-plus/icons-vue/-/icons-vue-2.1.0.tgz", - "integrity": "sha512-PSBn3elNoanENc1vnCfh+3WA9fimRC7n+fWkf3rE5jvv+aBohNHABC/KAR5KWPecxWxDTVT1ERpRbOMRcOV/vA==", - "requires": {} - }, - "@esbuild/android-arm": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.17.tgz", - "integrity": "sha512-wHsmJG/dnL3OkpAcwbgoBTTMHVi4Uyou3F5mf58ZtmUyIKfcdA7TROav/6tCzET4A3QW2Q2FC+eFneMU+iyOxg==", - "optional": true - }, - "@esbuild/android-arm64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.17.tgz", - "integrity": "sha512-9np+YYdNDed5+Jgr1TdWBsozZ85U1Oa3xW0c7TWqH0y2aGghXtZsuT8nYRbzOMcl0bXZXjOGbksoTtVOlWrRZg==", - "optional": true + "node_modules/jscodeshift/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, - "@esbuild/android-x64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.17.tgz", - "integrity": "sha512-O+FeWB/+xya0aLg23hHEM2E3hbfwZzjqumKMSIqcHbNvDa+dza2D0yLuymRBQQnC34CWrsJUXyH2MG5VnLd6uw==", - "optional": true + "node_modules/jscodeshift/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" + } }, - "@esbuild/darwin-arm64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.17.tgz", - "integrity": "sha512-M9uJ9VSB1oli2BE/dJs3zVr9kcCBBsE883prage1NWz6pBS++1oNn/7soPNS3+1DGj0FrkSvnED4Bmlu1VAE9g==", - "optional": true + "node_modules/jscodeshift/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } }, - "@esbuild/darwin-x64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.17.tgz", - "integrity": "sha512-XDre+J5YeIJDMfp3n0279DFNrGCXlxOuGsWIkRb1NThMZ0BsrWXoTg23Jer7fEXQ9Ye5QjrvXpxnhzl3bHtk0g==", - "optional": true + "node_modules/jscodeshift/node_modules/write-file-atomic": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } }, - "@esbuild/freebsd-arm64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.17.tgz", - "integrity": "sha512-cjTzGa3QlNfERa0+ptykyxs5A6FEUQQF0MuilYXYBGdBxD3vxJcKnzDlhDCa1VAJCmAxed6mYhA2KaJIbtiNuQ==", - "optional": true + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } }, - "@esbuild/freebsd-x64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.17.tgz", - "integrity": "sha512-sOxEvR8d7V7Kw8QqzxWc7bFfnWnGdaFBut1dRUYtu+EIRXefBc/eIsiUiShnW0hM3FmQ5Zf27suDuHsKgZ5QrA==", - "optional": true + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, - "@esbuild/linux-arm": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.17.tgz", - "integrity": "sha512-2d3Lw6wkwgSLC2fIvXKoMNGVaeY8qdN0IC3rfuVxJp89CRfA3e3VqWifGDfuakPmp90+ZirmTfye1n4ncjv2lg==", - "optional": true + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "dev": true }, - "@esbuild/linux-arm64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.17.tgz", - "integrity": "sha512-c9w3tE7qA3CYWjT+M3BMbwMt+0JYOp3vCMKgVBrCl1nwjAlOMYzEo+gG7QaZ9AtqZFj5MbUc885wuBBmu6aADQ==", - "optional": true + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, - "@esbuild/linux-ia32": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.17.tgz", - "integrity": "sha512-1DS9F966pn5pPnqXYz16dQqWIB0dmDfAQZd6jSSpiT9eX1NzKh07J6VKR3AoXXXEk6CqZMojiVDSZi1SlmKVdg==", - "optional": true + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" }, - "@esbuild/linux-loong64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.17.tgz", - "integrity": "sha512-EvLsxCk6ZF0fpCB6w6eOI2Fc8KW5N6sHlIovNe8uOFObL2O+Mr0bflPHyHwLT6rwMg9r77WOAWb2FqCQrVnwFg==", - "optional": true + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true }, - "@esbuild/linux-mips64el": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.17.tgz", - "integrity": "sha512-e0bIdHA5p6l+lwqTE36NAW5hHtw2tNRmHlGBygZC14QObsA3bD4C6sXLJjvnDIjSKhW1/0S3eDy+QmX/uZWEYQ==", - "optional": true + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } }, - "@esbuild/linux-ppc64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.17.tgz", - "integrity": "sha512-BAAilJ0M5O2uMxHYGjFKn4nJKF6fNCdP1E0o5t5fvMYYzeIqy2JdAP88Az5LHt9qBoUa4tDaRpfWt21ep5/WqQ==", - "optional": true + "node_modules/jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true }, - "@esbuild/linux-riscv64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.17.tgz", - "integrity": "sha512-Wh/HW2MPnC3b8BqRSIme/9Zhab36PPH+3zam5pqGRH4pE+4xTrVLx2+XdGp6fVS3L2x+DrsIcsbMleex8fbE6g==", - "optional": true + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } }, - "@esbuild/linux-s390x": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.17.tgz", - "integrity": "sha512-j/34jAl3ul3PNcK3pfI0NSlBANduT2UO5kZ7FCaK33XFv3chDhICLY8wJJWIhiQ+YNdQ9dxqQctRg2bvrMlYgg==", - "optional": true + "node_modules/jsprim": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz", + "integrity": "sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + } }, - "@esbuild/linux-x64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.17.tgz", - "integrity": "sha512-QM50vJ/y+8I60qEmFxMoxIx4de03pGo2HwxdBeFd4nMh364X6TIBZ6VQ5UQmPbQWUVWHWws5MmJXlHAXvJEmpQ==", - "optional": true + "node_modules/jstransformer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-1.0.0.tgz", + "integrity": "sha512-C9YK3Rf8q6VAPDCCU9fnqo3mAfOH6vUGnMcP4AQAYIEpWtfGLpwOTmZ+igtdK5y+VvI2n3CyYSzy4Qh34eq24A==", + "dev": true, + "dependencies": { + "is-promise": "^2.0.0", + "promise": "^7.0.1" + } }, - "@esbuild/netbsd-x64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.17.tgz", - "integrity": "sha512-/jGlhWR7Sj9JPZHzXyyMZ1RFMkNPjC6QIAan0sDOtIo2TYk3tZn5UDrkE0XgsTQCxWTTOcMPf9p6Rh2hXtl5TQ==", - "optional": true + "node_modules/jsx-ast-utils": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz", + "integrity": "sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==", + "dependencies": { + "array-includes": "^3.1.5", + "object.assign": "^4.1.3" + }, + "engines": { + "node": ">=4.0" + } }, - "@esbuild/openbsd-x64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.17.tgz", - "integrity": "sha512-rSEeYaGgyGGf4qZM2NonMhMOP/5EHp4u9ehFiBrg7stH6BYEEjlkVREuDEcQ0LfIl53OXLxNbfuIj7mr5m29TA==", - "optional": true + "node_modules/keygrip": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz", + "integrity": "sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==", + "dev": true, + "dependencies": { + "tsscmp": "1.0.6" + }, + "engines": { + "node": ">= 0.6" + } }, - "@esbuild/sunos-x64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.17.tgz", - "integrity": "sha512-Y7ZBbkLqlSgn4+zot4KUNYst0bFoO68tRgI6mY2FIM+b7ZbyNVtNbDP5y8qlu4/knZZ73fgJDlXID+ohY5zt5g==", - "optional": true + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "@esbuild/win32-arm64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.17.tgz", - "integrity": "sha512-bwPmTJsEQcbZk26oYpc4c/8PvTY3J5/QK8jM19DVlEsAB41M39aWovWoHtNm78sd6ip6prilxeHosPADXtEJFw==", - "optional": true + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "engines": { + "node": ">=6" + } }, - "@esbuild/win32-ia32": { + "node_modules/koa": { + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/koa/-/koa-2.14.1.tgz", + "integrity": "sha512-USJFyZgi2l0wDgqkfD27gL4YGno7TfUkcmOe6UOLFOVuN+J7FwnNu4Dydl4CUQzraM1lBAiGed0M9OVJoT0Kqw==", + "dev": true, + "dependencies": { + "accepts": "^1.3.5", + "cache-content-type": "^1.0.0", + "content-disposition": "~0.5.2", + "content-type": "^1.0.4", + "cookies": "~0.8.0", + "debug": "^4.3.2", + "delegates": "^1.0.0", + "depd": "^2.0.0", + "destroy": "^1.0.4", + "encodeurl": "^1.0.2", + "escape-html": "^1.0.3", + "fresh": "~0.5.2", + "http-assert": "^1.3.0", + "http-errors": "^1.6.3", + "is-generator-function": "^1.0.7", + "koa-compose": "^4.1.0", + "koa-convert": "^2.0.0", + "on-finished": "^2.3.0", + "only": "~0.0.2", + "parseurl": "^1.3.2", + "statuses": "^1.5.0", + "type-is": "^1.6.16", + "vary": "^1.1.2" + }, + "engines": { + "node": "^4.8.4 || ^6.10.1 || ^7.10.1 || >= 8.1.4" + } + }, + "node_modules/koa-compose": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-4.1.0.tgz", + "integrity": "sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw==", + "dev": true + }, + "node_modules/koa-convert": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/koa-convert/-/koa-convert-2.0.0.tgz", + "integrity": "sha512-asOvN6bFlSnxewce2e/DK3p4tltyfC4VM7ZwuTuepI7dEQVcvpyFuBcEARu1+Hxg8DIwytce2n7jrZtRlPrARA==", + "dev": true, + "dependencies": { + "co": "^4.6.0", + "koa-compose": "^4.1.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/koa-send": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/koa-send/-/koa-send-5.0.1.tgz", + "integrity": "sha512-tmcyQ/wXXuxpDxyNXv5yNNkdAMdFRqwtegBXUaowiQzUKqJehttS0x2j0eOZDQAyloAth5w6wwBImnFzkUz3pQ==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "http-errors": "^1.7.3", + "resolve-path": "^1.4.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/koa-static": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/koa-static/-/koa-static-5.0.0.tgz", + "integrity": "sha512-UqyYyH5YEXaJrf9S8E23GoJFQZXkBVJ9zYYMPGz919MSX1KuvAcycIuS0ci150HCoPf4XQVhQ84Qf8xRPWxFaQ==", + "dev": true, + "dependencies": { + "debug": "^3.1.0", + "koa-send": "^5.0.0" + }, + "engines": { + "node": ">= 7.6.0" + } + }, + "node_modules/koa-static/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/koa/node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/language-subtag-registry": { + "version": "0.3.22", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", + "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==" + }, + "node_modules/language-tags": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz", + "integrity": "sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==", + "dependencies": { + "language-subtag-registry": "~0.3.2" + } + }, + "node_modules/lazy-ass": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz", + "integrity": "sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw==", + "dev": true, + "engines": { + "node": "> 0.8" + } + }, + "node_modules/lazy-universal-dotenv": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/lazy-universal-dotenv/-/lazy-universal-dotenv-4.0.0.tgz", + "integrity": "sha512-aXpZJRnTkpK6gQ/z4nk+ZBLd/Qdp118cvPruLSIQzQNRhKwEcdXCOzXuF55VDqIiuAaY3UGZ10DJtvZzDcvsxg==", + "dev": true, + "dependencies": { + "app-root-dir": "^1.0.2", + "dotenv": "^16.0.0", + "dotenv-expand": "^10.0.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lilconfig": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/linkify-it": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-4.0.1.tgz", + "integrity": "sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==", + "dependencies": { + "uc.micro": "^1.0.1" + } + }, + "node_modules/linkifyjs": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/linkifyjs/-/linkifyjs-4.1.1.tgz", + "integrity": "sha512-zFN/CTVmbcVef+WaDXT63dNzzkfRBKT1j464NJQkV7iSgJU0sLBus9W0HBwnXK13/hf168pbrx/V/bjEHOXNHA==" + }, + "node_modules/listr2": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.14.0.tgz", + "integrity": "sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g==", + "dev": true, + "dependencies": { + "cli-truncate": "^2.1.0", + "colorette": "^2.0.16", + "log-update": "^4.0.0", + "p-map": "^4.0.0", + "rfdc": "^1.3.0", + "rxjs": "^7.5.1", + "through": "^2.3.8", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "enquirer": ">= 2.3.0 < 3" + }, + "peerDependenciesMeta": { + "enquirer": { + "optional": true + } + } + }, + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "peer": true, + "engines": { + "node": ">=6.11.5" + } + }, + "node_modules/local-pkg": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.4.3.tgz", + "integrity": "sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, + "node_modules/lodash-unified": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/lodash-unified/-/lodash-unified-1.0.3.tgz", + "integrity": "sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ==", + "peerDependencies": { + "@types/lodash-es": "*", + "lodash": "*", + "lodash-es": "*" + } + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "dev": true + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "dev": true + }, + "node_modules/lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", + "dev": true + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-symbols/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-symbols/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/log-symbols/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/log-symbols/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/log-symbols/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/log-symbols/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/log-update": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", + "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", + "dev": true, + "dependencies": { + "ansi-escapes": "^4.3.0", + "cli-cursor": "^3.1.0", + "slice-ansi": "^4.0.0", + "wrap-ansi": "^6.2.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-update/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/log-update/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/log-update/node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/logrocket": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/logrocket/-/logrocket-3.0.1.tgz", + "integrity": "sha512-jOWG+jEzobKVxGytzZ+4KGm2kiMQMRTHab2uDWQyVZcHfEF38BlCH1yjQVY4LCmuQUwZitP9biMzJZnyUQ0dtQ==" + }, + "node_modules/logrocket-vuex": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/logrocket-vuex/-/logrocket-vuex-0.0.3.tgz", + "integrity": "sha512-Xnl3pBEkc/bbtZ5JEtFwqNjVuLzVEohlBpyQHP47BlO+/6sFmSM2JcNWojysYUo4cp3IWpmWXcezax2+Cq4RsA==" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/loupe": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", + "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.1" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/lz-string": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "dev": true, + "bin": { + "lz-string": "bin/bin.js" + } + }, + "node_modules/magic-string": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.0.tgz", + "integrity": "sha512-LA+31JYDJLs82r2ScLrlz1GjSgu66ZV518eyWT+S8VhyQn/JL0u9MeBOvQMGYiPk1DBiSN9DDMOcXvigJZaViQ==", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.13" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/map-or-similar": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/map-or-similar/-/map-or-similar-1.5.0.tgz", + "integrity": "sha512-0aF7ZmVon1igznGI4VS30yugpduQW3y3GkcgGJOp7d8x8QrizhigUxjI/m2UojsXXto+jLAH3KSz+xOJTiORjg==", + "dev": true + }, + "node_modules/markdown-it": { + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-13.0.1.tgz", + "integrity": "sha512-lTlxriVoy2criHP0JKRhO2VDG9c2ypWCsT237eDiLqi09rmbKoUetyGHq2uOIRoRS//kfoJckS0eUzzkDR+k2Q==", + "dependencies": { + "argparse": "^2.0.1", + "entities": "~3.0.1", + "linkify-it": "^4.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + }, + "bin": { + "markdown-it": "bin/markdown-it.js" + } + }, + "node_modules/markdown-to-jsx": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-7.4.0.tgz", + "integrity": "sha512-zilc+MIkVVXPyTb4iIUTIz9yyqfcWjszGXnwF9K/aiBWcHXFcmdEMTkG01/oQhwSCH7SY1BnG6+ev5BzWmbPrg==", + "dev": true, + "engines": { + "node": ">= 10" + }, + "peerDependencies": { + "react": ">= 0.14.0" + } + }, + "node_modules/marked": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/mdast-util-definitions": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-4.0.0.tgz", + "integrity": "sha512-k8AJ6aNnUkB7IE+5azR9h81O5EQ/cTDXtWdMq9Kk5KcEW/8ritU5CeLg/9HhOC++nALHBlaogJ5jz0Ybk3kPMQ==", + "dev": true, + "dependencies": { + "unist-util-visit": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-string": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-1.1.0.tgz", + "integrity": "sha512-jVU0Nr2B9X3MU4tSK7JP1CMkSvOj7X5l/GboG1tKRw52lLF1x2Ju92Ms9tNetCcbfX3hzlM73zYo2NKkWSfF/A==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", + "dev": true + }, + "node_modules/mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==" + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/memoize-one": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", + "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==" + }, + "node_modules/memoizerific": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/memoizerific/-/memoizerific-1.11.3.tgz", + "integrity": "sha512-/EuHYwAPdLtXwAwSZkh/Gutery6pD2KYd44oQLhAvQp/50mpyduZh8Q7PYHXTCJ+wuXxt7oij2LXyIJOOYFPog==", + "dev": true, + "dependencies": { + "map-or-similar": "^1.5.0" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", + "dev": true + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/mini-css-extract-plugin": { + "version": "2.7.5", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.5.tgz", + "integrity": "sha512-9HaR++0mlgom81s95vvNjxkg52n2b5s//3ZTI1EtzFb98awsLSivs2LMsVqnQ3ay0PVhqWcGNyDaTE961FOcjQ==", + "dev": true, + "dependencies": { + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/mini-css-extract-plugin/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/mini-css-extract-plugin/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/mini-css-extract-plugin/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/mini-css-extract-plugin/node_modules/schema-utils": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", + "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.8.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/mitt": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.0.tgz", + "integrity": "sha512-7dX2/10ITVyqh4aOSVI9gdape+t9l2/8QxHrFmUXu4EEUpdlxl6RudZUPZoc+zuY2hk1j7XxVroIVIan/pD/SQ==" + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "dev": true + }, + "node_modules/mlly": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.2.0.tgz", + "integrity": "sha512-+c7A3CV0KGdKcylsI6khWyts/CYrGTrRVo4R/I7u/cUsy0Conxa6LUhiEzVKIw14lc2L5aiO4+SeVe4TeGRKww==", + "dev": true, + "dependencies": { + "acorn": "^8.8.2", + "pathe": "^1.1.0", + "pkg-types": "^1.0.2", + "ufo": "^1.1.1" + } + }, + "node_modules/moment": { + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", + "engines": { + "node": "*" + } + }, + "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==" + }, + "node_modules/nanoclone": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/nanoclone/-/nanoclone-0.2.1.tgz", + "integrity": "sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA==" + }, + "node_modules/nanoid": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" + }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + }, + "node_modules/node-dir": { + "version": "0.1.17", + "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz", + "integrity": "sha512-tmPX422rYgofd4epzrNoOXiE8XFZYOcCq1vD7MAXCDO+O+zndlA2ztdKKMa+EeuBG5tHETpr4ml4RGgpqDCCAg==", + "dev": true, + "dependencies": { + "minimatch": "^3.0.2" + }, + "engines": { + "node": ">= 0.10.5" + } + }, + "node_modules/node-emoji": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", + "integrity": "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==", + "dependencies": { + "lodash": "^4.17.21" + } + }, + "node_modules/node-fetch": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz", + "integrity": "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-fetch-native": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.1.tgz", + "integrity": "sha512-bW9T/uJDPAJB2YNYEpWzE54U5O3MQidXsOyTfnbKYtTtFexRvGzb1waphBN4ZwP6EcIvYYEOwW0b72BpAqydTw==", + "dev": true + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true + }, + "node_modules/node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" + }, + "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/normalize-package-data/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "devOptional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/normalize-wheel-es": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/normalize-wheel-es/-/normalize-wheel-es-1.2.0.tgz", + "integrity": "sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw==" + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nprogress": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz", + "integrity": "sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==" + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/nypm": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.3.6.tgz", + "integrity": "sha512-2CATJh3pd6CyNfU5VZM7qSwFu0ieyabkEdnogE30Obn1czrmOYiZ8DOZLe1yBdLKWoyD3Mcy2maUs+0MR3yVjQ==", + "dev": true, + "dependencies": { + "citty": "^0.1.5", + "execa": "^8.0.1", + "pathe": "^1.1.2", + "ufo": "^1.3.2" + }, + "bin": { + "nypm": "dist/cli.mjs" + }, + "engines": { + "node": "^14.16.0 || >=16.10.0" + } + }, + "node_modules/nypm/node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/nypm/node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nypm/node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, + "engines": { + "node": ">=16.17.0" + } + }, + "node_modules/nypm/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nypm/node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nypm/node_modules/npm-run-path": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.2.0.tgz", + "integrity": "sha512-W4/tgAXFqFA0iL7fk0+uQ3g7wkL8xJmx3XdK0VGb4cHW//eZTtKGvFBBoRKVTpY7n6ze4NL9ly7rgXcHufqXKg==", + "dev": true, + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nypm/node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nypm/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nypm/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/nypm/node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/object-inspect": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-is": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", + "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.6.tgz", + "integrity": "sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.6.tgz", + "integrity": "sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.hasown": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.2.tgz", + "integrity": "sha512-B5UIT3J1W+WuWIU55h0mjlwaqxiE5vYENJXIXZ4VFe05pNYrkKuK0U/6aFcb0pKywYJh7IhfoqUfKVmrJJHZHw==", + "dependencies": { + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.omit": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-3.0.0.tgz", + "integrity": "sha512-EO+BCv6LJfu+gBIF3ggLicFebFLN5zqzz/WWJlMFfkMyGth+oBkhxzDl0wx2W4GkLzuQs/FsSkXZb2IMWQqmBQ==", + "dependencies": { + "is-extendable": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.values": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", + "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ohash": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-1.1.3.tgz", + "integrity": "sha512-zuHHiGTYTA1sYJ/wZN+t5HKZaH23i4yI1HMwbuXm24Nid7Dv0KcuRlKoNKS9UNfAVSBlnGLcuQrnOKWOZoEGaw==", + "dev": true + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dev": true, + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/only": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/only/-/only-0.0.2.tgz", + "integrity": "sha512-Fvw+Jemq5fjjyWz6CpKx6w9s7xxqo3+JCyM0WXWeCSOboZ8ABkyvP8ID4CZuChA/wxSx+XSJmdOm8rGVyJ1hdQ==", + "dev": true + }, + "node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "dev": true, + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dev": true, + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ora/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/ora/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/ora/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/ora/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/ora/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/orderedmap": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/orderedmap/-/orderedmap-2.1.0.tgz", + "integrity": "sha512-/pIFexOm6S70EPdznemIz3BQZoJ4VTFrhqzu0ACBqBgeLsLxq8e6Jim63ImIfwW/zAD1AlXpRMlOv3aghmo4dA==" + }, + "node_modules/ospath": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/ospath/-/ospath-1.2.2.tgz", + "integrity": "sha512-o6E5qJV5zkAbIDNhGSIlyOhScKXgQrSRMilfph0clDfM0nEnBOlKlH4sWDmG95BW/CvwNz0vmm7dJVtU2KlMiA==", + "dev": true + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==", + "dev": true + }, + "node_modules/papaparse": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/papaparse/-/papaparse-5.4.1.tgz", + "integrity": "sha512-HipMsgJkZu8br23pW15uvo6sib6wne/4woLZPlFf3rpDyMe9ywEXUsuD7+6K9PRkJlVT51j/sCOYDKGGS3ZJrw==" + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "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" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-srcset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-srcset/-/parse-srcset-1.0.2.tgz", + "integrity": "sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q==" + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/path-scurry": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "dev": true, + "dependencies": { + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.1.0.tgz", + "integrity": "sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==", + "dev": true, + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/path-to-regexp": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz", + "integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==", + "dev": true + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "dev": true + }, + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/peek-stream": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/peek-stream/-/peek-stream-1.1.3.tgz", + "integrity": "sha512-FhJ+YbOSBb9/rIl2ZeE/QHEsWn7PqNYt8ARAY3kIgNGOk13g9FGyIY6JIl/xB/3TFRVoTv5as0l11weORrTekA==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "duplexify": "^3.5.0", + "through2": "^2.0.3" + } + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "dev": true + }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", + "dev": true + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "devOptional": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinia": { + "version": "2.0.33", + "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.0.33.tgz", + "integrity": "sha512-HOj1yVV2itw6rNIrR2f7+MirGNxhORjrULL8GWgRwXsGSvEqIQ+SE0MYt6cwtpegzCda3i+rVTZM+AM7CG+kRg==", + "dependencies": { + "@vue/devtools-api": "^6.5.0", + "vue-demi": "*" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "@vue/composition-api": "^1.4.0", + "typescript": ">=4.4.4", + "vue": "^2.6.14 || ^3.2.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/pinia/node_modules/vue-demi": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.11.tgz", + "integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==", + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", + "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", + "dev": true, + "dependencies": { + "find-up": "^5.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/pkg-types": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.0.2.tgz", + "integrity": "sha512-hM58GKXOcj8WTqUXnsQyJYXdeAPbythQgEF3nTcEo+nkD49chjQ9IKm/QJy9xf6JakXptz86h7ecP2024rrLaQ==", + "dev": true, + "dependencies": { + "jsonc-parser": "^3.2.0", + "mlly": "^1.1.1", + "pathe": "^1.1.0" + } + }, + "node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/polished": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/polished/-/polished-4.2.2.tgz", + "integrity": "sha512-Sz2Lkdxz6F2Pgnpi9U5Ng/WdWAUZxmHrNPoVlm3aAemxoy2Qy7LGjQg4uf8qKelDAUW94F4np3iH2YPf2qefcQ==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.17.8" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/portfinder": { + "version": "1.0.32", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.32.tgz", + "integrity": "sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg==", + "dev": true, + "dependencies": { + "async": "^2.6.4", + "debug": "^3.2.7", + "mkdirp": "^0.5.6" + }, + "engines": { + "node": ">= 0.12.0" + } + }, + "node_modules/portfinder/node_modules/async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "dev": true, + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/portfinder/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/postcss": { + "version": "8.4.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.27.tgz", + "integrity": "sha512-gY/ACJtJPSmUFPDCHtX78+01fHa64FaU4zaaWfuh1MhGJISufJAH4cun6k/8fwsHYeK4UQmENQK+tRLCFJE8JQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-calc": { + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.4.tgz", + "integrity": "sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.9", + "postcss-value-parser": "^4.2.0" + }, + "peerDependencies": { + "postcss": "^8.2.2" + } + }, + "node_modules/postcss-colormin": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.3.1.tgz", + "integrity": "sha512-UsWQG0AqTFQmpBegeLLc1+c3jIqBNB0zlDGRWR+dQ3pRKJL1oeMzyqmH3o2PIfn9MBdNrVPWhDbT769LxCTLJQ==", + "dev": true, + "dependencies": { + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0", + "colord": "^2.9.1", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-convert-values": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.1.3.tgz", + "integrity": "sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA==", + "dev": true, + "dependencies": { + "browserslist": "^4.21.4", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-comments": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz", + "integrity": "sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-duplicates": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz", + "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-empty": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz", + "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-overridden": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz", + "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-import": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-14.1.0.tgz", + "integrity": "sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-js": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", + "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "dev": true, + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-load-config": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", + "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", + "dev": true, + "dependencies": { + "lilconfig": "^2.0.5", + "yaml": "^1.10.2" + }, + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/postcss-merge-longhand": { + "version": "5.1.7", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.1.7.tgz", + "integrity": "sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0", + "stylehacks": "^5.1.1" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-merge-rules": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.1.4.tgz", + "integrity": "sha512-0R2IuYpgU93y9lhVbO/OylTtKMVcHb67zjWIfCiKR9rWL3GUk1677LAqD/BcHizukdZEjT8Ru3oHRoAYoJy44g==", + "dev": true, + "dependencies": { + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0", + "cssnano-utils": "^3.1.0", + "postcss-selector-parser": "^6.0.5" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-font-values": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz", + "integrity": "sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-gradients": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz", + "integrity": "sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==", + "dev": true, + "dependencies": { + "colord": "^2.9.1", + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-params": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.1.4.tgz", + "integrity": "sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw==", + "dev": true, + "dependencies": { + "browserslist": "^4.21.4", + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-selectors": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz", + "integrity": "sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.5" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-nested": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.0.tgz", + "integrity": "sha512-0DkamqrPcmkBDsLn+vQDIrtkSbNkv5AD/M322ySo9kqFkCIYklym2xEmWkwo+Y3/qZo34tzEPNUw4y7yMCdv5w==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": ">=12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-normalize-charset": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz", + "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-display-values": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz", + "integrity": "sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-positions": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz", + "integrity": "sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-repeat-style": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz", + "integrity": "sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-string": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz", + "integrity": "sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-timing-functions": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz", + "integrity": "sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-unicode": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.1.tgz", + "integrity": "sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA==", + "dev": true, + "dependencies": { + "browserslist": "^4.21.4", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz", + "integrity": "sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==", + "dev": true, + "dependencies": { + "normalize-url": "^6.0.1", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-whitespace": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz", + "integrity": "sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-ordered-values": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz", + "integrity": "sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==", + "dev": true, + "dependencies": { + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-reduce-initial": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.1.2.tgz", + "integrity": "sha512-dE/y2XRaqAi6OvjzD22pjTUQ8eOfc6m/natGHgKFBK9DxFmIm69YmaRVQrGgFlEfc1HePIurY0TmDeROK05rIg==", + "dev": true, + "dependencies": { + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-reduce-transforms": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz", + "integrity": "sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.11", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.11.tgz", + "integrity": "sha512-zbARubNdogI9j7WY4nQJBiNqQf3sLS3wCP4WfOidu+p28LofJqDH1tcXypGrcmMHhDk2t9wGhCsYe/+szLTy1g==", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-svgo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.1.0.tgz", + "integrity": "sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0", + "svgo": "^2.7.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-unique-selectors": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz", + "integrity": "sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.5" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/pretty-bytes": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", + "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/pretty-format/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "node_modules/pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "dev": true, + "dependencies": { + "asap": "~2.0.3" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/property-expr": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.5.tgz", + "integrity": "sha512-IJUkICM5dP5znhCckHSv30Q4b5/JA5enCtkRHYaOVOAocnH/1BQEYTC5NMfT3AVl/iXKdr3aqQbQn9DxyWknwA==" + }, + "node_modules/prosemirror-changeset": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/prosemirror-changeset/-/prosemirror-changeset-2.2.0.tgz", + "integrity": "sha512-QM7ohGtkpVpwVGmFb8wqVhaz9+6IUXcIQBGZ81YNAKYuHiFJ1ShvSzab4pKqTinJhwciZbrtBEk/2WsqSt2PYg==", + "dependencies": { + "prosemirror-transform": "^1.0.0" + } + }, + "node_modules/prosemirror-collab": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/prosemirror-collab/-/prosemirror-collab-1.3.0.tgz", + "integrity": "sha512-+S/IJ69G2cUu2IM5b3PBekuxs94HO1CxJIWOFrLQXUaUDKL/JfBx+QcH31ldBlBXyDEUl+k3Vltfi1E1MKp2mA==", + "dependencies": { + "prosemirror-state": "^1.0.0" + } + }, + "node_modules/prosemirror-commands": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/prosemirror-commands/-/prosemirror-commands-1.5.1.tgz", + "integrity": "sha512-ga1ga/RkbzxfAvb6iEXYmrEpekn5NCwTb8w1dr/gmhSoaGcQ0VPuCzOn5qDEpC45ql2oDkKoKQbRxLJwKLpMTQ==", + "dependencies": { + "prosemirror-model": "^1.0.0", + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.0.0" + } + }, + "node_modules/prosemirror-dropcursor": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/prosemirror-dropcursor/-/prosemirror-dropcursor-1.8.0.tgz", + "integrity": "sha512-TZMitR8nlp9Xh42pDYGcWopCoFPmJduoyGJ7FjYM2/7gZKnfD41TIaZN5Q1cQjm6Fm/P5vk/DpVYFhS8kDdigw==", + "dependencies": { + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.1.0", + "prosemirror-view": "^1.1.0" + } + }, + "node_modules/prosemirror-gapcursor": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/prosemirror-gapcursor/-/prosemirror-gapcursor-1.3.1.tgz", + "integrity": "sha512-GKTeE7ZoMsx5uVfc51/ouwMFPq0o8YrZ7Hx4jTF4EeGbXxBveUV8CGv46mSHuBBeXGmvu50guoV2kSnOeZZnUA==", + "dependencies": { + "prosemirror-keymap": "^1.0.0", + "prosemirror-model": "^1.0.0", + "prosemirror-state": "^1.0.0", + "prosemirror-view": "^1.0.0" + } + }, + "node_modules/prosemirror-history": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/prosemirror-history/-/prosemirror-history-1.3.1.tgz", + "integrity": "sha512-YMV/IWBZ+LZSfaNcBbPcaQUiAiJRYFyJW2aapuNzL8nhIRsI7fIO0ykJFSe802+mWeoTsVJ1jxvRWPYqaUqljQ==", + "dependencies": { + "prosemirror-state": "^1.2.2", + "prosemirror-transform": "^1.0.0", + "prosemirror-view": "^1.31.0", + "rope-sequence": "^1.3.0" + } + }, + "node_modules/prosemirror-inputrules": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/prosemirror-inputrules/-/prosemirror-inputrules-1.2.0.tgz", + "integrity": "sha512-eAW/M/NTSSzpCOxfR8Abw6OagdG0MiDAiWHQMQveIsZtoKVYzm0AflSPq/ymqJd56/Su1YPbwy9lM13wgHOFmQ==", + "dependencies": { + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.0.0" + } + }, + "node_modules/prosemirror-keymap": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prosemirror-keymap/-/prosemirror-keymap-1.2.1.tgz", + "integrity": "sha512-kVK6WGC+83LZwuSJnuCb9PsADQnFZllt94qPP3Rx/vLcOUV65+IbBeH2nS5cFggPyEVJhGkGrgYFRrG250WhHQ==", + "dependencies": { + "prosemirror-state": "^1.0.0", + "w3c-keyname": "^2.2.0" + } + }, + "node_modules/prosemirror-markdown": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/prosemirror-markdown/-/prosemirror-markdown-1.10.1.tgz", + "integrity": "sha512-s7iaTLiX+qO5z8kF2NcMmy2T7mIlxzkS4Sp3vTKSYChPtbMpg6YxFkU0Y06rUg2WtKlvBu7v1bXzlGBkfjUWAA==", + "dependencies": { + "markdown-it": "^13.0.1", + "prosemirror-model": "^1.0.0" + } + }, + "node_modules/prosemirror-menu": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prosemirror-menu/-/prosemirror-menu-1.2.1.tgz", + "integrity": "sha512-sBirXxVfHalZO4f1ZS63WzewINK4182+7dOmoMeBkqYO8wqMBvBS7wQuwVOHnkMWPEh0+N0LJ856KYUN+vFkmQ==", + "dependencies": { + "crelt": "^1.0.0", + "prosemirror-commands": "^1.0.0", + "prosemirror-history": "^1.0.0", + "prosemirror-state": "^1.0.0" + } + }, + "node_modules/prosemirror-model": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.19.0.tgz", + "integrity": "sha512-/CvFGJnwc41EJSfDkQLly1cAJJJmBpZwwUJtwZPTjY2RqZJfM8HVbCreOY/jti8wTRbVyjagcylyGoeJH/g/3w==", + "dependencies": { + "orderedmap": "^2.0.0" + } + }, + "node_modules/prosemirror-schema-basic": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prosemirror-schema-basic/-/prosemirror-schema-basic-1.2.1.tgz", + "integrity": "sha512-vYBdIHsYKSDIqYmPBC7lnwk9DsKn8PnVqK97pMYP5MLEDFqWIX75JiaJTzndBii4bRuNqhC2UfDOfM3FKhlBHg==", + "dependencies": { + "prosemirror-model": "^1.19.0" + } + }, + "node_modules/prosemirror-schema-list": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/prosemirror-schema-list/-/prosemirror-schema-list-1.2.2.tgz", + "integrity": "sha512-rd0pqSDp86p0MUMKG903g3I9VmElFkQpkZ2iOd3EOVg1vo5Cst51rAsoE+5IPy0LPXq64eGcCYlW1+JPNxOj2w==", + "dependencies": { + "prosemirror-model": "^1.0.0", + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.0.0" + } + }, + "node_modules/prosemirror-state": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/prosemirror-state/-/prosemirror-state-1.4.2.tgz", + "integrity": "sha512-puuzLD2mz/oTdfgd8msFbe0A42j5eNudKAAPDB0+QJRw8cO1ygjLmhLrg9RvDpf87Dkd6D4t93qdef00KKNacQ==", + "dependencies": { + "prosemirror-model": "^1.0.0", + "prosemirror-transform": "^1.0.0", + "prosemirror-view": "^1.27.0" + } + }, + "node_modules/prosemirror-tables": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/prosemirror-tables/-/prosemirror-tables-1.3.2.tgz", + "integrity": "sha512-/9JTeN6s58Zq66HXaxP6uf8PAmc7XXKZFPlOGVtLvxEd6xBP6WtzaJB9wBjiGUzwbdhdMEy7V62yuHqk/3VrnQ==", + "dependencies": { + "prosemirror-keymap": "^1.1.2", + "prosemirror-model": "^1.8.1", + "prosemirror-state": "^1.3.1", + "prosemirror-transform": "^1.2.1", + "prosemirror-view": "^1.13.3" + } + }, + "node_modules/prosemirror-trailing-node": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/prosemirror-trailing-node/-/prosemirror-trailing-node-2.0.4.tgz", + "integrity": "sha512-0Yl9w7IdHkaCdqR+NE3FOucePME4OmiGcybnF1iasarEILP5U8+4xTnl53yafULjmwcg1SrSG65Hg7Zk2H2v3g==", + "dependencies": { + "@babel/runtime": "^7.21.0", + "@remirror/core-constants": "^2.0.1", + "@remirror/core-helpers": "^2.0.2", + "escape-string-regexp": "^4.0.0" + }, + "peerDependencies": { + "prosemirror-model": "^1.19.0", + "prosemirror-state": "^1.4.2", + "prosemirror-view": "^1.30.2" + } + }, + "node_modules/prosemirror-trailing-node/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/prosemirror-transform": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/prosemirror-transform/-/prosemirror-transform-1.7.1.tgz", + "integrity": "sha512-VteoifAfpt46z0yEt6Fc73A5OID9t/y2QIeR5MgxEwTuitadEunD/V0c9jQW8ziT8pbFM54uTzRLJ/nLuQjMxg==", + "dependencies": { + "prosemirror-model": "^1.0.0" + } + }, + "node_modules/prosemirror-view": { + "version": "1.31.2", + "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.31.2.tgz", + "integrity": "sha512-d/HKgUsaKzMQnr5tGRdZq+8GSixOTyYI69hoNV417VlciTvUDFSr4SWsRNUzhMRwvT6xVLI8yrVWERHjNWI6uw==", + "dependencies": { + "prosemirror-model": "^1.16.0", + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.1.0" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "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": "sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A==", + "dev": true + }, + "node_modules/psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", + "dev": true + }, + "node_modules/pug": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pug/-/pug-3.0.2.tgz", + "integrity": "sha512-bp0I/hiK1D1vChHh6EfDxtndHji55XP/ZJKwsRqrz6lRia6ZC2OZbdAymlxdVFwd1L70ebrVJw4/eZ79skrIaw==", + "dev": true, + "dependencies": { + "pug-code-gen": "^3.0.2", + "pug-filters": "^4.0.0", + "pug-lexer": "^5.0.1", + "pug-linker": "^4.0.0", + "pug-load": "^3.0.0", + "pug-parser": "^6.0.0", + "pug-runtime": "^3.0.1", + "pug-strip-comments": "^2.0.0" + } + }, + "node_modules/pug-attrs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pug-attrs/-/pug-attrs-3.0.0.tgz", + "integrity": "sha512-azINV9dUtzPMFQktvTXciNAfAuVh/L/JCl0vtPCwvOA21uZrC08K/UnmrL+SXGEVc1FwzjW62+xw5S/uaLj6cA==", + "dev": true, + "dependencies": { + "constantinople": "^4.0.1", + "js-stringify": "^1.0.2", + "pug-runtime": "^3.0.0" + } + }, + "node_modules/pug-code-gen": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pug-code-gen/-/pug-code-gen-3.0.2.tgz", + "integrity": "sha512-nJMhW16MbiGRiyR4miDTQMRWDgKplnHyeLvioEJYbk1RsPI3FuA3saEP8uwnTb2nTJEKBU90NFVWJBk4OU5qyg==", + "dev": true, + "dependencies": { + "constantinople": "^4.0.1", + "doctypes": "^1.1.0", + "js-stringify": "^1.0.2", + "pug-attrs": "^3.0.0", + "pug-error": "^2.0.0", + "pug-runtime": "^3.0.0", + "void-elements": "^3.1.0", + "with": "^7.0.0" + } + }, + "node_modules/pug-error": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pug-error/-/pug-error-2.0.0.tgz", + "integrity": "sha512-sjiUsi9M4RAGHktC1drQfCr5C5eriu24Lfbt4s+7SykztEOwVZtbFk1RRq0tzLxcMxMYTBR+zMQaG07J/btayQ==", + "dev": true + }, + "node_modules/pug-filters": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pug-filters/-/pug-filters-4.0.0.tgz", + "integrity": "sha512-yeNFtq5Yxmfz0f9z2rMXGw/8/4i1cCFecw/Q7+D0V2DdtII5UvqE12VaZ2AY7ri6o5RNXiweGH79OCq+2RQU4A==", + "dev": true, + "dependencies": { + "constantinople": "^4.0.1", + "jstransformer": "1.0.0", + "pug-error": "^2.0.0", + "pug-walk": "^2.0.0", + "resolve": "^1.15.1" + } + }, + "node_modules/pug-lexer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/pug-lexer/-/pug-lexer-5.0.1.tgz", + "integrity": "sha512-0I6C62+keXlZPZkOJeVam9aBLVP2EnbeDw3An+k0/QlqdwH6rv8284nko14Na7c0TtqtogfWXcRoFE4O4Ff20w==", + "dev": true, + "dependencies": { + "character-parser": "^2.2.0", + "is-expression": "^4.0.0", + "pug-error": "^2.0.0" + } + }, + "node_modules/pug-linker": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pug-linker/-/pug-linker-4.0.0.tgz", + "integrity": "sha512-gjD1yzp0yxbQqnzBAdlhbgoJL5qIFJw78juN1NpTLt/mfPJ5VgC4BvkoD3G23qKzJtIIXBbcCt6FioLSFLOHdw==", + "dev": true, + "dependencies": { + "pug-error": "^2.0.0", + "pug-walk": "^2.0.0" + } + }, + "node_modules/pug-load": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pug-load/-/pug-load-3.0.0.tgz", + "integrity": "sha512-OCjTEnhLWZBvS4zni/WUMjH2YSUosnsmjGBB1An7CsKQarYSWQ0GCVyd4eQPMFJqZ8w9xgs01QdiZXKVjk92EQ==", + "dev": true, + "dependencies": { + "object-assign": "^4.1.1", + "pug-walk": "^2.0.0" + } + }, + "node_modules/pug-parser": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/pug-parser/-/pug-parser-6.0.0.tgz", + "integrity": "sha512-ukiYM/9cH6Cml+AOl5kETtM9NR3WulyVP2y4HOU45DyMim1IeP/OOiyEWRr6qk5I5klpsBnbuHpwKmTx6WURnw==", + "dev": true, + "dependencies": { + "pug-error": "^2.0.0", + "token-stream": "1.0.0" + } + }, + "node_modules/pug-runtime": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/pug-runtime/-/pug-runtime-3.0.1.tgz", + "integrity": "sha512-L50zbvrQ35TkpHwv0G6aLSuueDRwc/97XdY8kL3tOT0FmhgG7UypU3VztfV/LATAvmUfYi4wNxSajhSAeNN+Kg==", + "dev": true + }, + "node_modules/pug-strip-comments": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pug-strip-comments/-/pug-strip-comments-2.0.0.tgz", + "integrity": "sha512-zo8DsDpH7eTkPHCXFeAk1xZXJbyoTfdPlNR0bK7rpOMuhBYb0f5qUVCO1xlsitYd3w5FQTK7zpNVKb3rZoUrrQ==", + "dev": true, + "dependencies": { + "pug-error": "^2.0.0" + } + }, + "node_modules/pug-walk": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pug-walk/-/pug-walk-2.0.0.tgz", + "integrity": "sha512-yYELe9Q5q9IQhuvqsZNwA5hfPkMJ8u92bQLIMcsMxf/VADjNtEYptU+inlufAFYcWdHlwNfZOEnOOQrZrcyJCQ==", + "dev": true + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "dependencies": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + } + }, + "node_modules/pumpify/node_modules/pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/puppeteer-core": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-2.1.1.tgz", + "integrity": "sha512-n13AWriBMPYxnpbb6bnaY5YoY6rGj8vPLrz6CZF3o0qJNEwlcfJVxBzYZ0NJsQ21UbdJoijPCDrM++SUVEz7+w==", + "dev": true, + "dependencies": { + "@types/mime-types": "^2.1.0", + "debug": "^4.1.0", + "extract-zip": "^1.6.6", + "https-proxy-agent": "^4.0.0", + "mime": "^2.0.3", + "mime-types": "^2.1.25", + "progress": "^2.0.1", + "proxy-from-env": "^1.0.0", + "rimraf": "^2.6.1", + "ws": "^6.1.0" + }, + "engines": { + "node": ">=8.16.0" + } + }, + "node_modules/puppeteer-core/node_modules/extract-zip": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz", + "integrity": "sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==", + "dev": true, + "dependencies": { + "concat-stream": "^1.6.2", + "debug": "^2.6.9", + "mkdirp": "^0.5.4", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" + } + }, + "node_modules/puppeteer-core/node_modules/extract-zip/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/puppeteer-core/node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/puppeteer-core/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/puppeteer-core/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/puppeteer-core/node_modules/ws": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz", + "integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==", + "dev": true, + "dependencies": { + "async-limiter": "~1.0.0" + } + }, + "node_modules/qs": { + "version": "6.11.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.1.tgz", + "integrity": "sha512-0wsrzgTz/kAVIeuxSjnpGC56rzYtr6JT/2BwEvMaPhFIoYa1aGO8LbzuU1R0uUYQkLpWBTOj0l/CLAJB64J6nQ==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ramda": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.27.2.tgz", + "integrity": "sha512-SbiLPU40JuJniHexQSAgad32hfwd+DRUdwF2PlVuI5RZD0/vahUco7R8vD86J/tcEKKF9vZrUVwgtmGCqlCKyA==" + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "dev": true, + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/react": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "dev": true, + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-colorful": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/react-colorful/-/react-colorful-5.6.1.tgz", + "integrity": "sha512-1exovf0uGTGyq5mXQT0zgQ80uvj2PCwvF8zY1RN9/vbJVSjSo3fsB/4L3ObbF7u70NduSiK4xu4Y6q1MHoUGEw==", + "dev": true, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/react-dom": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", + "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "dev": true, + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.0" + }, + "peerDependencies": { + "react": "^18.2.0" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "node_modules/react-remove-scroll": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.5.5.tgz", + "integrity": "sha512-ImKhrzJJsyXJfBZ4bzu8Bwpka14c/fQt0k+cyFp/PBhTfyDnU5hjOtM4AG/0AMyy8oKzOTR0lDgJIM7pYXI0kw==", + "dev": true, + "dependencies": { + "react-remove-scroll-bar": "^2.3.3", + "react-style-singleton": "^2.2.1", + "tslib": "^2.1.0", + "use-callback-ref": "^1.3.0", + "use-sidecar": "^1.1.2" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-remove-scroll-bar": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.4.tgz", + "integrity": "sha512-63C4YQBUt0m6ALadE9XV56hV8BgJWDmmTPY758iIJjfQKt2nYwoUrPk0LXRXcB/yIj82T1/Ixfdpdk68LwIB0A==", + "dev": true, + "dependencies": { + "react-style-singleton": "^2.2.1", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-style-singleton": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.1.tgz", + "integrity": "sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==", + "dev": true, + "dependencies": { + "get-nonce": "^1.0.0", + "invariant": "^2.2.4", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, + "dependencies": { + "pify": "^2.3.0" + } + }, + "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/read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "dependencies": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg/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/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "devOptional": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/recast": { + "version": "0.23.4", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.4.tgz", + "integrity": "sha512-qtEDqIZGVcSZCHniWwZWbRy79Dc6Wp3kT/UmDA2RJKBPg7+7k51aQBZirHmUGn5uvHf2rg8DkjizrN26k61ATw==", + "dev": true, + "dependencies": { + "assert": "^2.0.0", + "ast-types": "^0.16.1", + "esprima": "~4.0.0", + "source-map": "~0.6.1", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", + "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", + "dev": true, + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" + }, + "node_modules/regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", + "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexpu-core": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", + "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "dev": true, + "dependencies": { + "@babel/regjsgen": "^0.8.0", + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.1.0", + "regjsparser": "^0.9.1", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsparser": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "dev": true, + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/remark-external-links": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/remark-external-links/-/remark-external-links-8.0.0.tgz", + "integrity": "sha512-5vPSX0kHoSsqtdftSHhIYofVINC8qmp0nctkeU9YoJwV3YfiBRiI6cbFRJ0oI/1F9xS+bopXG0m2KS8VFscuKA==", + "dev": true, + "dependencies": { + "extend": "^3.0.0", + "is-absolute-url": "^3.0.0", + "mdast-util-definitions": "^4.0.0", + "space-separated-tokens": "^1.0.0", + "unist-util-visit": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-slug": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/remark-slug/-/remark-slug-6.1.0.tgz", + "integrity": "sha512-oGCxDF9deA8phWvxFuyr3oSJsdyUAxMFbA0mZ7Y1Sas+emILtO+e5WutF9564gDsEN4IXaQXm5pFo6MLH+YmwQ==", + "dev": true, + "dependencies": { + "github-slugger": "^1.0.0", + "mdast-util-to-string": "^1.0.0", + "unist-util-visit": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/replace-in-file": { + "version": "6.3.5", + "resolved": "https://registry.npmjs.org/replace-in-file/-/replace-in-file-6.3.5.tgz", + "integrity": "sha512-arB9d3ENdKva2fxRnSjwBEXfK1npgyci7ZZuwysgAp7ORjHSyxz6oqIjTEv8R0Ydl4Ll7uOAZXL4vbkhGIizCg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.2", + "glob": "^7.2.0", + "yargs": "^17.2.1" + }, + "bin": { + "replace-in-file": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/replace-in-file/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/replace-in-file/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/replace-in-file/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/replace-in-file/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/replace-in-file/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/replace-in-file/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/request-progress": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz", + "integrity": "sha512-MnWzEHHaxHO2iWiQuHrUPBi/1WeBf5PkxQqNyNvLl9VAYSdXkP8tQ3pBSeCPD+yw0v0Aq1zosWLz0BdeXpWwZg==", + "dev": true, + "dependencies": { + "throttleit": "^1.0.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/requireindex": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz", + "integrity": "sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==", + "dev": true, + "engines": { + "node": ">=0.10.5" + } + }, + "node_modules/resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "dependencies": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-path": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/resolve-path/-/resolve-path-1.4.0.tgz", + "integrity": "sha512-i1xevIst/Qa+nA9olDxLWnLk8YZbi8R/7JPbCMcgyWaFR6bKWaexgJgEB5oc2PKMjYdrHynyz0NY+if+H98t1w==", + "dev": true, + "dependencies": { + "http-errors": "~1.6.2", + "path-is-absolute": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/resolve-path/node_modules/http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "dev": true, + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/resolve-path/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "dev": true + }, + "node_modules/resolve-path/node_modules/setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", + "dev": true + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rollup": { + "version": "3.26.3", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.26.3.tgz", + "integrity": "sha512-7Tin0C8l86TkpcMtXvQu6saWH93nhG3dGQ1/+l5V2TDMceTxO7kDiK6GzbfLWNNxqJXm591PcEZUozZm51ogwQ==", + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=14.18.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/rollup-plugin-visualizer": { + "version": "5.9.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-visualizer/-/rollup-plugin-visualizer-5.9.2.tgz", + "integrity": "sha512-waHktD5mlWrYFrhOLbti4YgQCn1uR24nYsNuXxg7LkPH8KdTXVWR9DNY1WU0QqokyMixVXJS4J04HNrVTMP01A==", + "dev": true, + "dependencies": { + "open": "^8.4.0", + "picomatch": "^2.3.1", + "source-map": "^0.7.4", + "yargs": "^17.5.1" + }, + "bin": { + "rollup-plugin-visualizer": "dist/bin/cli.js" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "rollup": "2.x || 3.x" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/rollup-plugin-visualizer/node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/rope-sequence": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rope-sequence/-/rope-sequence-1.3.3.tgz", + "integrity": "sha512-85aZYCxweiD5J8yTEbw+E6A27zSnLPNDL0WfPdw3YYodq7WjnTKo0q4dtyQ2gz23iPT8Q9CUyJtAaUNcTxRf5Q==" + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rxjs": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.0.tgz", + "integrity": "sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==", + "dev": true, + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "node_modules/sanitize-html": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.10.0.tgz", + "integrity": "sha512-JqdovUd81dG4k87vZt6uA6YhDfWkUGruUu/aPmXLxXi45gZExnt9Bnw/qeQU8oGf82vPyaE0vO4aH0PbobB9JQ==", + "dependencies": { + "deepmerge": "^4.2.2", + "escape-string-regexp": "^4.0.0", + "htmlparser2": "^8.0.0", + "is-plain-object": "^5.0.0", + "parse-srcset": "^1.0.2", + "postcss": "^8.3.11" + } + }, + "node_modules/sanitize-html/node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/sanitize-html/node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/sanitize-html/node_modules/domutils": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz", + "integrity": "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.1" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/sanitize-html/node_modules/entities": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", + "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/sanitize-html/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/sanitize-html/node_modules/htmlparser2": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", + "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "entities": "^4.4.0" + } + }, + "node_modules/sass": { + "version": "1.60.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.60.0.tgz", + "integrity": "sha512-updbwW6fNb5gGm8qMXzVO7V4sWf7LMXnMly/JEyfbfERbVH46Fn6q02BX7/eHTdKpE7d+oTkMMQpFWNUMfFbgQ==", + "devOptional": true, + "dependencies": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/scheduler": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", + "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", + "dev": true, + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/scule": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/scule/-/scule-1.0.0.tgz", + "integrity": "sha512-4AsO/FrViE/iDNEPaAQlb77tf0csuq27EsVpy6ett584EcRTp6pTDLoGWVxCD77y5iU5FauOvhsI4o1APwPoSQ==", + "dev": true + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/send/node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/send/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", + "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dev": true, + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.0.tgz", + "integrity": "sha512-QHsz8GgQIGKlRi24yFc6a6lN69Idnx634w49ay6+jA5yFh7a1UY+4Rp6HPx/L/1zcEDPEij8cIsiqR6bQsE5VQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", + "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/slice-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/socket.io-client": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.6.1.tgz", + "integrity": "sha512-5UswCV6hpaRsNg5kkEHVcbBIXEYoVbMQaHJBXJCyEQ+CiFPV1NIOY0XOFWG4XR4GZcB8Kn6AsRs/9cy9TbqVMQ==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.2", + "engine.io-client": "~6.4.0", + "socket.io-parser": "~4.2.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-parser": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.2.tgz", + "integrity": "sha512-DJtziuKypFkMMHCm2uIshOYC7QaylbtzQwiMYDuCKy3OPkjLzu4B2vAhTlqipRHHzrI0NJeBAizTK7X+6m1jVw==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/sortablejs": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.14.0.tgz", + "integrity": "sha512-pBXvQCs5/33fdN1/39pPL0NZF20LeRbLQ5jtnheIPN9JQAaufGjKdWduZn4U7wCtVuzKhmRkI0DFYHYRbB2H1w==" + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/space-separated-tokens": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz", + "integrity": "sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/spawn-command": { + "version": "0.0.2-1", + "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz", + "integrity": "sha512-n98l9E2RMSJ9ON1AKisHzz7V42VDiBQGY6PB1BwRglz99wpVsSuGzQ+jOi6lFXBGVTCrRpltvjm+/XA+tpeJrg==", + "dev": true + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.4.0.tgz", + "integrity": "sha512-hcjppoJ68fhxA/cjbN4T8N6uCUejN8yFw69ttpqtBeCbF3u13n7mb31NB9jKwGTTWWnt9IbRA/mf1FprYS8wfw==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.16", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.16.tgz", + "integrity": "sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==", + "dev": true + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "node_modules/sshpk": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", + "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", + "dev": true, + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", + "deprecated": "Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility", + "dev": true + }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/stop-iteration-iterator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", + "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", + "dependencies": { + "internal-slot": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/store2": { + "version": "2.14.2", + "resolved": "https://registry.npmjs.org/store2/-/store2-2.14.2.tgz", + "integrity": "sha512-siT1RiqlfQnGqgT/YzXVUNsom9S0H1OX+dpdGN1xkyYATo4I6sep5NmsRD/40s3IIOvlCq6akxkqG82urIZW1w==", + "dev": true + }, + "node_modules/storybook": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/storybook/-/storybook-7.6.10.tgz", + "integrity": "sha512-ypFeGhQTUBBfqSUVZYh7wS5ghn3O2wILCiQc4459SeUpvUn+skcqw/TlrwGSoF5EWjDA7gtRrWDxO3mnlPt5Cw==", + "dev": true, + "dependencies": { + "@storybook/cli": "7.6.10" + }, + "bin": { + "sb": "index.js", + "storybook": "index.js" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/stream-shift": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz", + "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==", + "dev": true + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/string-width/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz", + "integrity": "sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "regexp.prototype.flags": "^1.4.3", + "side-channel": "^1.0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", + "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", + "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", + "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "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": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-literal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-1.0.1.tgz", + "integrity": "sha512-QZTsipNpa2Ppr6v1AmJHESqJ3Uz247MUS0OjrnnZjFAvEoWqxuyFuXn2xLgMtRnijJShAa1HL0gtJyUs7u7n3Q==", + "dev": true, + "dependencies": { + "acorn": "^8.8.2" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/stylehacks": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.1.tgz", + "integrity": "sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==", + "dev": true, + "dependencies": { + "browserslist": "^4.21.4", + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/svgo": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", + "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", + "dev": true, + "dependencies": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^4.1.3", + "css-tree": "^1.1.3", + "csso": "^4.2.0", + "picocolors": "^1.0.0", + "stable": "^0.1.8" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/svgo/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/synchronous-promise": { + "version": "2.0.17", + "resolved": "https://registry.npmjs.org/synchronous-promise/-/synchronous-promise-2.0.17.tgz", + "integrity": "sha512-AsS729u2RHUfEra9xJrE39peJcc2stq2+poBXX8bcM08Y6g9j/i/PUzwNQqkaJde7Ntg1TO7bSREbR5sdosQ+g==", + "dev": true + }, + "node_modules/tailwind-config-viewer": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/tailwind-config-viewer/-/tailwind-config-viewer-1.7.2.tgz", + "integrity": "sha512-3JJCeAAlvG+i/EBj+tQb0x4weo30QjdSAo4hlcnVbtD+CkpzHi/UwU9InbPMcYH+ESActoa2kCyjpLEyjEkn0Q==", + "dev": true, + "dependencies": { + "@koa/router": "^9.0.1", + "commander": "^6.0.0", + "fs-extra": "^9.0.1", + "koa": "^2.12.0", + "koa-static": "^5.0.0", + "open": "^7.0.4", + "portfinder": "^1.0.26", + "replace-in-file": "^6.1.0" + }, + "bin": { + "tailwind-config-viewer": "cli/index.js", + "tailwindcss-config-viewer": "cli/index.js" + }, + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "tailwindcss": "1 || 2 || 2.0.1-compat || 3" + } + }, + "node_modules/tailwind-config-viewer/node_modules/commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/tailwind-config-viewer/node_modules/open": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", + "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", + "dev": true, + "dependencies": { + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tailwindcss": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.2.7.tgz", + "integrity": "sha512-B6DLqJzc21x7wntlH/GsZwEXTBttVSl1FtCzC8WP4oBc/NKef7kaax5jeihkkCEWc831/5NDJ9gRNDK6NEioQQ==", + "dev": true, + "dependencies": { + "arg": "^5.0.2", + "chokidar": "^3.5.3", + "color-name": "^1.1.4", + "detective": "^5.2.1", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.2.12", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "lilconfig": "^2.0.6", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.0.9", + "postcss-import": "^14.1.0", + "postcss-js": "^4.0.0", + "postcss-load-config": "^3.1.4", + "postcss-nested": "6.0.0", + "postcss-selector-parser": "^6.0.11", + "postcss-value-parser": "^4.2.0", + "quick-lru": "^5.1.1", + "resolve": "^1.22.1" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=12.13.0" + }, + "peerDependencies": { + "postcss": "^8.0.9" + } + }, + "node_modules/tailwindcss/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", + "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", + "dev": true, + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dev": true, + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-fs/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/telejson": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/telejson/-/telejson-7.2.0.tgz", + "integrity": "sha512-1QTEcJkJEhc8OnStBx/ILRu5J2p0GjvWsBx56bmZRqnrkdBMUe+nX92jxV+p3dB4CP6PZCdJMQJwCggkNBMzkQ==", + "dev": true, + "dependencies": { + "memoizerific": "^1.11.3" + } + }, + "node_modules/temp": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.4.tgz", + "integrity": "sha512-s0ZZzd0BzYv5tLSptZooSjK8oj6C+c19p7Vqta9+6NPOf7r+fxq0cJe6/oN4LTC79sy5NY8ucOJNgwsKCSbfqg==", + "dev": true, + "dependencies": { + "rimraf": "~2.6.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/temp-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", + "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/temp/node_modules/rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/tempy": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tempy/-/tempy-1.0.1.tgz", + "integrity": "sha512-biM9brNqxSc04Ee71hzFbryD11nX7VPhQQY32AdDmjFvodsRFz/3ufeoTZ6uYkRFfGo188tENcASNs3vTdsM0w==", + "dev": true, + "dependencies": { + "del": "^6.0.0", + "is-stream": "^2.0.0", + "temp-dir": "^2.0.0", + "type-fest": "^0.16.0", + "unique-string": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tempy/node_modules/type-fest": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", + "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/terser": { + "version": "5.16.8", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.8.tgz", + "integrity": "sha512-QI5g1E/ef7d+PsDifb+a6nnVgC4F22Bg6T0xrBrz6iloVB4PUkkunp6V8nzoOOZJIzjWVdAGqCdlKlhLq/TbIA==", + "dependencies": { + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.3.7", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.7.tgz", + "integrity": "sha512-AfKwIktyP7Cu50xNjXF/6Qb5lBNzYaWpU6YfoX3uZicTx0zTy0stDDCsvjDapKsSDvOeWo5MEq4TmdBy2cNoHw==", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.17", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.1", + "terser": "^5.16.5" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/terser-webpack-plugin/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/terser-webpack-plugin/node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/terser-webpack-plugin/node_modules/schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/terser-webpack-plugin/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==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" + }, + "node_modules/throttle-debounce": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-3.0.1.tgz", + "integrity": "sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg==", + "engines": { + "node": ">=10" + } + }, + "node_modules/throttleit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", + "integrity": "sha512-rkTVqu6IjfQ/6+uNuuc3sZek4CEYxTJom3IktzgdSxcZqdARuebbA/f4QmAxMQIxqq9ZLEUkSYqvuk1I6VKq4g==", + "dev": true + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true + }, + "node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/through2/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/through2/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/through2/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/through2/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/tiny-emitter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", + "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==" + }, + "node_modules/tiny-invariant": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.1.tgz", + "integrity": "sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==", + "dev": true + }, + "node_modules/tinyspy": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.0.tgz", + "integrity": "sha512-d2eda04AN/cPOR89F7Xv5bK/jrQEhmcLFe6HFldoeO9AJtps+fqEnh486vnT/8y4bw38pSyxDcTCAq+Ks2aJTg==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tippy.js": { + "version": "6.3.7", + "resolved": "https://registry.npmjs.org/tippy.js/-/tippy.js-6.3.7.tgz", + "integrity": "sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ==", + "dependencies": { + "@popperjs/core": "^2.9.0" + } + }, + "node_modules/tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "dev": true, + "dependencies": { + "rimraf": "^3.0.0" + }, + "engines": { + "node": ">=8.17.0" + } + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "devOptional": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tocbot": { + "version": "4.25.0", + "resolved": "https://registry.npmjs.org/tocbot/-/tocbot-4.25.0.tgz", + "integrity": "sha512-kE5wyCQJ40hqUaRVkyQ4z5+4juzYsv/eK+aqD97N62YH0TxFhzJvo22RUQQZdO3YnXAk42ZOfOpjVdy+Z0YokA==", + "dev": true + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/token-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/token-stream/-/token-stream-1.0.0.tgz", + "integrity": "sha512-VSsyNPPW74RpHwR8Fc21uubwHY7wMDeJLys2IX5zJNih+OnAnaifKHo+1LHT7DAdloQ7apeaaWg8l7qnf/TnEg==", + "dev": true + }, + "node_modules/toposort": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", + "integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==" + }, + "node_modules/tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/ts-dedent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz", + "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==", + "dev": true, + "engines": { + "node": ">=6.10" + } + }, + "node_modules/ts-map": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ts-map/-/ts-map-1.0.3.tgz", + "integrity": "sha512-vDWbsl26LIcPGmDpoVzjEP6+hvHZkBkLW7JpvwbCv/5IYPJlsbzCVXY3wsCeAxAUeTclNOUZxnLdGh3VBD/J6w==", + "dev": true + }, + "node_modules/tsconfig-paths": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", + "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/tslib": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", + "dev": true + }, + "node_modules/tsscmp": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz", + "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==", + "dev": true, + "engines": { + "node": ">=0.6.x" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "dev": true + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", + "dev": true + }, + "node_modules/typescript": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", + "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", + "devOptional": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=12.20" + } + }, + "node_modules/uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==" + }, + "node_modules/ufo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.3.2.tgz", + "integrity": "sha512-o+ORpgGwaYQXgqGDwd+hkS4PuZ3QnmqMMxRuajK/a38L6fTpcE5GPIfrf+L/KemFzfUpeUQc1rRS1iDBozvnFA==", + "dev": true + }, + "node_modules/uglify-js": { + "version": "3.17.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", + "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", + "dev": true, + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dev": true, + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", + "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unimport": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/unimport/-/unimport-3.0.4.tgz", + "integrity": "sha512-eoof/HLiNJcIkVpnqc7sJbzKSLx39J6xTaP7E4ElgVQKeq2t9fPTkvJKcA55IJTaRPkEkDq8kcc/IZPmrypnFg==", + "dev": true, + "dependencies": { + "@rollup/pluginutils": "^5.0.2", + "escape-string-regexp": "^5.0.0", + "fast-glob": "^3.2.12", + "local-pkg": "^0.4.3", + "magic-string": "^0.30.0", + "mlly": "^1.2.0", + "pathe": "^1.1.0", + "pkg-types": "^1.0.2", + "scule": "^1.0.0", + "strip-literal": "^1.0.1", + "unplugin": "^1.3.1" + } + }, + "node_modules/unimport/node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "dev": true, + "dependencies": { + "crypto-random-string": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/unist-util-is": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.1.0.tgz", + "integrity": "sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz", + "integrity": "sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==", + "dev": true, + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz", + "integrity": "sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==", + "dev": true, + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/universal-user-agent": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", + "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unleash-proxy-client": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/unleash-proxy-client/-/unleash-proxy-client-2.4.3.tgz", + "integrity": "sha512-ILJIHNSeh7ajHczemNE19Rl3NpVU3voFouYIgWCbJd+OhuJ9elfpuD1LF5yucEJq8AuWKkEM2AzUFFOTiv/2Sw==", + "dependencies": { + "tiny-emitter": "^2.1.0", + "uuid": "^8.3.2" + } + }, + "node_modules/unleash-proxy-client/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/unplugin": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.3.1.tgz", + "integrity": "sha512-h4uUTIvFBQRxUKS2Wjys6ivoeofGhxzTe2sRWlooyjHXVttcVfV/JiavNd3d4+jty0SVV0dxGw9AkY9MwiaCEw==", + "dev": true, + "dependencies": { + "acorn": "^8.8.2", + "chokidar": "^3.5.3", + "webpack-sources": "^3.2.3", + "webpack-virtual-modules": "^0.5.0" + } + }, + "node_modules/unplugin-auto-import": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/unplugin-auto-import/-/unplugin-auto-import-0.15.2.tgz", + "integrity": "sha512-Wivfu+xccgvEZG8QtZcIvt6napfX9wyOFqM//7FHOtev8+k+dp3ykiqsEl6TODgHmqTTBeQX4Ah1JvRgUNjlkg==", + "dev": true, + "dependencies": { + "@antfu/utils": "^0.7.2", + "@rollup/pluginutils": "^5.0.2", + "local-pkg": "^0.4.3", + "magic-string": "^0.30.0", + "minimatch": "^7.4.3", + "unimport": "^3.0.3", + "unplugin": "^1.3.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@nuxt/kit": "^3.2.2", + "@vueuse/core": "*" + }, + "peerDependenciesMeta": { + "@nuxt/kit": { + "optional": true + }, + "@vueuse/core": { + "optional": true + } + } + }, + "node_modules/unplugin-auto-import/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/unplugin-auto-import/node_modules/minimatch": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.3.tgz", + "integrity": "sha512-5UB4yYusDtkRPbRiy1cqZ1IpGNcJCGlEMG17RKzPddpyiPKoCdwohbED8g4QXT0ewCt8LTkQXuljsUfQ3FKM4A==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/unplugin-vue-components": { + "version": "0.24.1", + "resolved": "https://registry.npmjs.org/unplugin-vue-components/-/unplugin-vue-components-0.24.1.tgz", + "integrity": "sha512-T3A8HkZoIE1Cja95xNqolwza0yD5IVlgZZ1PVAGvVCx8xthmjsv38xWRCtHtwl+rvZyL9uif42SRkDGw9aCfMA==", + "dev": true, + "dependencies": { + "@antfu/utils": "^0.7.2", + "@rollup/pluginutils": "^5.0.2", + "chokidar": "^3.5.3", + "debug": "^4.3.4", + "fast-glob": "^3.2.12", + "local-pkg": "^0.4.3", + "magic-string": "^0.30.0", + "minimatch": "^7.4.2", + "resolve": "^1.22.1", + "unplugin": "^1.1.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@babel/parser": "^7.15.8", + "@nuxt/kit": "^3.2.2", + "vue": "2 || 3" + }, + "peerDependenciesMeta": { + "@babel/parser": { + "optional": true + }, + "@nuxt/kit": { + "optional": true + } + } + }, + "node_modules/unplugin-vue-components/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/unplugin-vue-components/node_modules/minimatch": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.3.tgz", + "integrity": "sha512-5UB4yYusDtkRPbRiy1cqZ1IpGNcJCGlEMG17RKzPddpyiPKoCdwohbED8g4QXT0ewCt8LTkQXuljsUfQ3FKM4A==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/unplugin/node_modules/webpack-virtual-modules": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.5.0.tgz", + "integrity": "sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==", + "dev": true + }, + "node_modules/untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/url-search-params-polyfill": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/url-search-params-polyfill/-/url-search-params-polyfill-7.0.1.tgz", + "integrity": "sha512-bAw7L2E+jn9XHG5P9zrPnHdO0yJub4U+yXJOdpcpkr7OBd9T8oll4lUos0iSGRcDvfZoLUKfx9a6aNmIhJ4+mQ==" + }, + "node_modules/use-callback-ref": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.1.tgz", + "integrity": "sha512-Lg4Vx1XZQauB42Hw3kK7JM6yjVjgFmFC5/Ab797s79aARomD2nEErc4mCgM8EZrARLmmbWpi5DGCadmK50DcAQ==", + "dev": true, + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-resize-observer": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/use-resize-observer/-/use-resize-observer-9.1.0.tgz", + "integrity": "sha512-R25VqO9Wb3asSD4eqtcxk8sJalvIOYBqS8MNZlpDSQ4l4xMQxC/J7Id9HoTqPq8FwULIn0PVW+OAqF2dyYbjow==", + "dev": true, + "dependencies": { + "@juggle/resize-observer": "^3.3.1" + }, + "peerDependencies": { + "react": "16.8.0 - 18", + "react-dom": "16.8.0 - 18" + } + }, + "node_modules/use-sidecar": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.2.tgz", + "integrity": "sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw==", + "dev": true, + "dependencies": { + "detect-node-es": "^1.1.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.9.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "dev": true, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.0.tgz", + "integrity": "sha512-fX6Z5o4m6XsXBdli9g7DtWgAx+osMsRRZFKma1mIUsLCz6vRvv+pz5VNbyu9UEDzpMWulZfvpgb/cmDXVulYFQ==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v-network-graph": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/v-network-graph/-/v-network-graph-0.8.2.tgz", + "integrity": "sha512-JmuP07z1+/nmZs/6/2x0IU978VrikcOC5ZsC8H9+jEZUzqoEftYfenQRRncGU6YQWAdj0uMxFMb+acYLGYyxog==", + "dependencies": { + "@dash14/svg-pan-zoom": "^3.6.9", + "mitt": "^3.0.0" + }, + "peerDependencies": { + "d3-force": "^3.0.0", + "vue": "^3.2.45" + } + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/vite": { + "version": "4.4.7", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.4.7.tgz", + "integrity": "sha512-6pYf9QJ1mHylfVh39HpuSfMPojPSKVxZvnclX1K1FyZ1PXDOcLBibdq5t1qxJSnL63ca8Wf4zts6mD8u8oc9Fw==", + "dependencies": { + "esbuild": "^0.18.10", + "postcss": "^8.4.26", + "rollup": "^3.25.2" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + }, + "peerDependencies": { + "@types/node": ">= 14", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/void-elements": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", + "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/vue": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.3.1.tgz", + "integrity": "sha512-3Rwy4I5idbPVSDZu6I+fFh6tdDSZbauImCTqLxE7y0LpHtiDvPeY01OI7RkFPbva1nk4hoO0sv/NzosH2h60sg==", + "dependencies": { + "@vue/compiler-dom": "3.3.1", + "@vue/compiler-sfc": "3.3.1", + "@vue/runtime-dom": "3.3.1", + "@vue/server-renderer": "3.3.1", + "@vue/shared": "3.3.1" + } + }, + "node_modules/vue-3-sanitize": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/vue-3-sanitize/-/vue-3-sanitize-0.1.4.tgz", + "integrity": "sha512-8+iU+MC94ibyOBUpn4g2hk8Dy32M7PKIi3UoUG+6Pd47J/uHIDdOdeXEEmCM/rVdyFqNXqLfO+yZT2BesGNlXA==", + "dependencies": { + "sanitize-html": "^2.0.0" + } + }, + "node_modules/vue-component-type-helpers": { + "version": "1.8.27", + "resolved": "https://registry.npmjs.org/vue-component-type-helpers/-/vue-component-type-helpers-1.8.27.tgz", + "integrity": "sha512-0vOfAtI67UjeO1G6UiX5Kd76CqaQ67wrRZiOe7UAb9Jm6GzlUr/fC7CV90XfwapJRjpCMaZFhv1V0ajWRmE9Dg==", + "dev": true + }, + "node_modules/vue-docgen-api": { + "version": "4.75.1", + "resolved": "https://registry.npmjs.org/vue-docgen-api/-/vue-docgen-api-4.75.1.tgz", + "integrity": "sha512-MECZ3uExz+ssmhD/2XrFoQQs93y17IVO1KDYTp8nr6i9GNrk67AAto6QAtilW1H/pTDPMkQxJ7w/25ZIqVtfAA==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.21.4", + "@babel/types": "^7.21.4", + "@vue/compiler-dom": "^3.2.0", + "@vue/compiler-sfc": "^3.2.0", + "ast-types": "^0.16.1", + "hash-sum": "^2.0.0", + "lru-cache": "^8.0.3", + "pug": "^3.0.2", + "recast": "^0.23.1", + "ts-map": "^1.0.3", + "vue-inbrowser-compiler-independent-utils": "^4.69.0" + }, + "peerDependencies": { + "vue": ">=2" + } + }, + "node_modules/vue-docgen-api/node_modules/lru-cache": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-8.0.5.tgz", + "integrity": "sha512-MhWWlVnuab1RG5/zMRRcVGXZLCXrZTgfwMikgzCegsPnG62yDQo5JnqKkrK4jO5iKqDAZGItAqN5CtKBCBWRUA==", + "dev": true, + "engines": { + "node": ">=16.14" + } + }, + "node_modules/vue-draggable-next": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/vue-draggable-next/-/vue-draggable-next-2.2.1.tgz", + "integrity": "sha512-EAMS1IRHF0kZO0o5PMOinsQsXIqsrKT1hKmbICxG3UEtn7zLFkLxlAtajcCcUTisNvQ6TtCB5COjD9a1raNADw==", + "peerDependencies": { + "sortablejs": "^1.14.0", + "vue": "^3.2.2" + } + }, + "node_modules/vue-eslint-parser": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.2.1.tgz", + "integrity": "sha512-tPOex4n6jit4E7h68auOEbDMwE58XiP4dylfaVTCOVCouR45g+QFDBjgIdEU52EXJxKyjgh91dLfN2rxUcV0bQ==", + "dependencies": { + "debug": "^4.3.4", + "eslint-scope": "^7.1.1", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.3.1", + "esquery": "^1.4.0", + "lodash": "^4.17.21", + "semver": "^7.3.6" + }, + "engines": { + "node": "^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=6.0.0" + } + }, + "node_modules/vue-eslint-parser/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/vue-eslint-parser/node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/vue-eslint-parser/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/vue-grid-layout": { + "version": "3.0.0-beta1", + "resolved": "https://registry.npmjs.org/vue-grid-layout/-/vue-grid-layout-3.0.0-beta1.tgz", + "integrity": "sha512-MsW0yfYNtnAO/uDhfZvkP6effxSJxvhAFbIL37x6Rn3vW9xf0WHVefKaSbQMLpSq3mXnR6ut0pg2Cd5lqIIZzg==", + "dependencies": { + "@interactjs/actions": "^1.10.2", + "@interactjs/auto-start": "^1.10.2", + "@interactjs/dev-tools": "^1.10.2", + "@interactjs/interactjs": "^1.10.2", + "@interactjs/modifiers": "^1.10.2", + "element-resize-detector": "^1.2.1", + "mitt": "^2.1.0" + } + }, + "node_modules/vue-grid-layout/node_modules/mitt": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-2.1.0.tgz", + "integrity": "sha512-ILj2TpLiysu2wkBbWjAmww7TkZb65aiQO+DkVdUTBpBXq+MHYiETENkKFMtsJZX1Lf4pe4QOrTSjIfUwN5lRdg==" + }, + "node_modules/vue-inbrowser-compiler-independent-utils": { + "version": "4.71.1", + "resolved": "https://registry.npmjs.org/vue-inbrowser-compiler-independent-utils/-/vue-inbrowser-compiler-independent-utils-4.71.1.tgz", + "integrity": "sha512-K3wt3iVmNGaFEOUR4JIThQRWfqokxLfnPslD41FDZB2ajXp789+wCqJyGYlIFsvEQ2P61PInw6/ph5iiqg51gg==", + "dev": true, + "peerDependencies": { + "vue": ">=2" + } + }, + "node_modules/vue-json-pretty": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/vue-json-pretty/-/vue-json-pretty-2.2.4.tgz", + "integrity": "sha512-JX80b3QDrspcH43C53CdtYeq/froApQGSV5y43bEMWFj2LGOxB96aH1VmvrFA21nD1WTP6nwfFMQqGXuS4jyFQ==", + "engines": { + "node": ">= 10.0.0", + "npm": ">= 5.0.0" + }, + "peerDependencies": { + "vue": ">=3.0.0" + } + }, + "node_modules/vue-loader": { + "version": "16.8.3", + "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.8.3.tgz", + "integrity": "sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA==", + "dependencies": { + "chalk": "^4.1.0", + "hash-sum": "^2.0.0", + "loader-utils": "^2.0.0" + }, + "peerDependencies": { + "webpack": "^4.1.0 || ^5.0.0-0" + } + }, + "node_modules/vue-loader/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/vue-loader/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/vue-loader/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/vue-loader/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/vue-loader/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/vue-loader/node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/vue-loader/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/vue-router": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.1.6.tgz", + "integrity": "sha512-DYWYwsG6xNPmLq/FmZn8Ip+qrhFEzA14EI12MsMgVxvHFDYvlr4NXpVF5hrRH1wVcDP8fGi5F4rxuJSl8/r+EQ==", + "dependencies": { + "@vue/devtools-api": "^6.4.5" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "vue": "^3.2.0" + } + }, + "node_modules/vue3-click-away": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/vue3-click-away/-/vue3-click-away-1.2.4.tgz", + "integrity": "sha512-O9Z2KlvIhJT8OxaFy04eiZE9rc1Mk/bp+70dLok68ko3Kr8AW5dU+j8avSk4GDQu94FllSr4m5ul4BpzlKOw1A==" + }, + "node_modules/vue3-lazyload": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/vue3-lazyload/-/vue3-lazyload-0.3.6.tgz", + "integrity": "sha512-UcVnEN9JzxeFBa7nNAPWKXHTtvVAzWYhBSvRU+Gmx9MdTGLWKwjZiNSyB1Os25jr9HaFHWY0DaU8uugXkGu9Gw==", + "dependencies": { + "vue-demi": "^0.12.5" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^2.0.0 || >=3.0.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/vue3-lazyload/node_modules/vue-demi": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.12.5.tgz", + "integrity": "sha512-BREuTgTYlUr0zw0EZn3hnhC3I6gPWv+Kwh4MCih6QcAeaTlaIX0DwOVN0wHej7hSvDPecz4jygy/idsgKfW58Q==", + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/vuedraggable": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/vuedraggable/-/vuedraggable-4.1.0.tgz", + "integrity": "sha512-FU5HCWBmsf20GpP3eudURW3WdWTKIbEIQxh9/8GE806hydR9qZqRRxRE3RjqX7PkuLuMQG/A7n3cfj9rCEchww==", + "dependencies": { + "sortablejs": "1.14.0" + }, + "peerDependencies": { + "vue": "^3.0.1" + } + }, + "node_modules/vuex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/vuex/-/vuex-4.1.0.tgz", + "integrity": "sha512-hmV6UerDrPcgbSy9ORAtNXDr9M4wlNP4pEFKye4ujJF8oqgFFuxDCdOLS3eNoRTtq5O3hoBDh9Doj1bQMYHRbQ==", + "dependencies": { + "@vue/devtools-api": "^6.0.0-beta.11" + }, + "peerDependencies": { + "vue": "^3.2.0" + } + }, + "node_modules/w3c-keyname": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.6.tgz", + "integrity": "sha512-f+fciywl1SJEniZHD6H+kUO8gOnwIr7f4ijKA6+ZvJFjeGi1r4PDLl53Ayud9O/rk64RqgoQine0feoeOU0kXg==" + }, + "node_modules/wait-on": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-6.0.1.tgz", + "integrity": "sha512-zht+KASY3usTY5u2LgaNqn/Cd8MukxLGjdcZxT2ns5QzDmTFc4XoWBgC+C/na+sMRZTuVygQoMYwdcVjHnYIVw==", + "dev": true, + "dependencies": { + "axios": "^0.25.0", + "joi": "^17.6.0", + "lodash": "^4.17.21", + "minimist": "^1.2.5", + "rxjs": "^7.5.4" + }, + "bin": { + "wait-on": "bin/wait-on" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/wait-on/node_modules/axios": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.25.0.tgz", + "integrity": "sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g==", + "dev": true, + "dependencies": { + "follow-redirects": "^1.14.7" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/watchpack": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", + "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dev": true, + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/webpack": { + "version": "5.82.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.82.1.tgz", + "integrity": "sha512-C6uiGQJ+Gt4RyHXXYt+v9f+SN1v83x68URwgxNQ98cvH8kxiuywWGP4XeNZ1paOzZ63aY3cTciCEQJNFUljlLw==", + "peer": true, + "dependencies": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^1.0.0", + "@webassemblyjs/ast": "^1.11.5", + "@webassemblyjs/wasm-edit": "^1.11.5", + "@webassemblyjs/wasm-parser": "^1.11.5", + "acorn": "^8.7.1", + "acorn-import-assertions": "^1.7.6", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.14.0", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.1.2", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.7", + "watchpack": "^2.4.0", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "peer": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/webpack/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "peer": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/webpack/node_modules/schema-utils": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.2.tgz", + "integrity": "sha512-pvjEHOgWc9OWA/f/DE3ohBWTD6EleVLf7iFUkoSwAxttdBhB9QUebQgxER2kWueOvRJXPHNnyrvvh9eZINB8Eg==", + "peer": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", + "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", + "dependencies": { + "is-map": "^2.0.1", + "is-set": "^2.0.1", + "is-weakmap": "^2.0.1", + "is-weakset": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", + "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/with": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/with/-/with-7.0.2.tgz", + "integrity": "sha512-RNGKj82nUPg3g5ygxkQl0R937xLyho1J24ItRCBTr/m1YnZkzJy1hUiHUJrc/VlsDQzsCnInEGSg3bci0Lmd4w==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.9.6", + "@babel/types": "^7.9.6", + "assert-never": "^1.2.1", + "babel-walk": "3.0.0-canary-5" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "dev": true + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/ws": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xml-name-validator": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", + "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/xmlhttprequest-ssl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz", + "integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "dev": true, + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "node_modules/ylru": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/ylru/-/ylru-1.3.2.tgz", + "integrity": "sha512-RXRJzMiK6U2ye0BlGGZnmpwJDPgakn6aNQ0A7gHRbD4I0uvK4TW6UqkK1V0pp9jskjJBAXd3dRrbzWkqJ+6cxA==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yup": { + "version": "0.32.11", + "resolved": "https://registry.npmjs.org/yup/-/yup-0.32.11.tgz", + "integrity": "sha512-Z2Fe1bn+eLstG8DRR6FTavGD+MeAwyfmouhHsIUgaADz8jvFKbO/fXc2trJKZg+5EBjh4gGm3iU/t3onKlXHIg==", + "dependencies": { + "@babel/runtime": "^7.15.4", + "@types/lodash": "^4.14.175", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "nanoclone": "^0.2.1", + "property-expr": "^2.0.4", + "toposort": "^2.0.2" + }, + "engines": { + "node": ">=10" + } + } + }, + "dependencies": { + "@adobe/css-tools": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.3.3.tgz", + "integrity": "sha512-rE0Pygv0sEZ4vBWHlAgJLGDU7Pm8xoO6p3wsEceb7GYAjScrOHpEo8KK/eVkAcnSM+slAEtXjA2JpdjLp4fJQQ==", + "dev": true + }, + "@ampproject/remapping": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", + "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "requires": { + "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@antfu/utils": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/@antfu/utils/-/utils-0.7.2.tgz", + "integrity": "sha512-vy9fM3pIxZmX07dL+VX1aZe7ynZ+YyB0jY+jE6r3hOK6GNY2t6W8rzpFC4tgpbXUYABkFQwgJq2XYXlxbXAI0g==", + "dev": true + }, + "@aw-web-design/x-default-browser": { + "version": "1.4.126", + "resolved": "https://registry.npmjs.org/@aw-web-design/x-default-browser/-/x-default-browser-1.4.126.tgz", + "integrity": "sha512-Xk1sIhyNC/esHGGVjL/niHLowM0csl/kFO5uawBy4IrWwy0o1G8LGt3jP6nmWGz+USxeeqbihAmp/oVZju6wug==", + "dev": true, + "requires": { + "default-browser-id": "3.0.0" + } + }, + "@babel/code-frame": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "requires": { + "@babel/highlight": "^7.23.4", + "chalk": "^2.4.2" + } + }, + "@babel/compat-data": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", + "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==" + }, + "@babel/core": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.7.tgz", + "integrity": "sha512-+UpDgowcmqe36d4NwqvKsyPMlOLNGMsfMmQ5WGCu+siCe3t3dfe9njrzGfdN4qq+bcNUt0+Vw6haRxBOycs4dw==", + "requires": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helpers": "^7.23.7", + "@babel/parser": "^7.23.6", + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.7", + "@babel/types": "^7.23.6", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + } + }, + "@babel/generator": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", + "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", + "requires": { + "@babel/types": "^7.23.6", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "dependencies": { + "@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + } + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", + "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz", + "integrity": "sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==", + "dev": true, + "requires": { + "@babel/types": "^7.22.15" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", + "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", + "requires": { + "@babel/compat-data": "^7.23.5", + "@babel/helper-validator-option": "^7.23.5", + "browserslist": "^4.22.2", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + } + }, + "@babel/helper-create-class-features-plugin": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.23.7.tgz", + "integrity": "sha512-xCoqR/8+BoNnXOY7RVSgv6X+o7pmT5q1d+gGcRlXYkI+9B31glE4jeejhKVpA04O1AtzOt7OSQ6VYKP5FcRl9g==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-member-expression-to-functions": "^7.23.0", + "@babel/helper-optimise-call-expression": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.20", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "semver": "^6.3.1" + } + }, + "@babel/helper-create-regexp-features-plugin": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz", + "integrity": "sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "regexpu-core": "^5.3.1", + "semver": "^6.3.1" + } + }, + "@babel/helper-define-polyfill-provider": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.5.0.tgz", + "integrity": "sha512-NovQquuQLAQ5HuyjCz7WQP9MjRj7dx++yspwiyUiGl9ZyadHRSql1HZh5ogRd8W8w6YM6EQ/NTB8rgjLt5W65Q==", + "dev": true, + "requires": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + } + }, + "@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==" + }, + "@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "requires": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz", + "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==", + "dev": true, + "requires": { + "@babel/types": "^7.23.0" + } + }, + "@babel/helper-module-imports": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "requires": { + "@babel/types": "^7.22.15" + } + }, + "@babel/helper-module-transforms": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", + "requires": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz", + "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==" + }, + "@babel/helper-remap-async-to-generator": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz", + "integrity": "sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-wrap-function": "^7.22.20" + } + }, + "@babel/helper-replace-supers": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz", + "integrity": "sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-member-expression-to-functions": "^7.22.15", + "@babel/helper-optimise-call-expression": "^7.22.5" + } + }, + "@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz", + "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-string-parser": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", + "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==" + }, + "@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==" + }, + "@babel/helper-validator-option": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==" + }, + "@babel/helper-wrap-function": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz", + "integrity": "sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.22.5", + "@babel/template": "^7.22.15", + "@babel/types": "^7.22.19" + } + }, + "@babel/helpers": { + "version": "7.23.8", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.8.tgz", + "integrity": "sha512-KDqYz4PiOWvDFrdHLPhKtCThtIcKVy6avWD2oG4GEvyQ+XDZwHD4YQd+H2vNMnq2rkdxsDkU82T+Vk8U/WXHRQ==", + "requires": { + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.7", + "@babel/types": "^7.23.6" + } + }, + "@babel/highlight": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "requires": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.6.tgz", + "integrity": "sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==" + }, + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.23.3.tgz", + "integrity": "sha512-iRkKcCqb7iGnq9+3G6rZ+Ciz5VywC4XNRHe57lKM+jOeYAoR0lVqdeeDRfh0tQcTfw/+vBhHn926FmQhLtlFLQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.23.3.tgz", + "integrity": "sha512-WwlxbfMNdVEpQjZmK5mhm7oSwD3dS6eU+Iwsi4Knl9wAletWem7kaRsGOG+8UEbRyqxY4SS5zvtfXwX+jMxUwQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-transform-optional-chaining": "^7.23.3" + } + }, + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.23.7.tgz", + "integrity": "sha512-LlRT7HgaifEpQA1ZgLVOIJZZFVPWN5iReq/7/JixwBtwcoeVGDBD53ZV28rrsLYOZs1Y/EHhA8N/Z6aazHR8cw==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-proposal-export-namespace-from": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz", + "integrity": "sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + } + }, + "@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "dev": true, + "requires": {} + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.12.13" + } + }, + "@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-syntax-flow": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.23.3.tgz", + "integrity": "sha512-YZiAIpkJAwQXBJLIQbRFayR5c+gJ35Vcz3bg954k7cd73zqjvhacJuL9RbrzPz8qPmZdgqP6EUKwy0PCNhaaPA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-syntax-import-assertions": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.23.3.tgz", + "integrity": "sha512-lPgDSU+SJLK3xmFDTV2ZRQAiM7UuUjGidwBywFavObCiZc1BeAAcMtHJKUya92hPHO+at63JJPLygilZard8jw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-syntax-import-attributes": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.23.3.tgz", + "integrity": "sha512-pawnE0P9g10xgoP7yKr6CK63K2FMsTE+FZidZO/1PwRdzmAPVs+HS1mAURUsgaoxammTJvULUdIkEK0gOcU2tA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-jsx": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz", + "integrity": "sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-typescript": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz", + "integrity": "sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-arrow-functions": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.23.3.tgz", + "integrity": "sha512-NzQcQrzaQPkaEwoTm4Mhyl8jI1huEL/WWIEvudjTCMJ9aBZNpsJbMASx7EQECtQQPS/DcnFpo0FIh3LvEO9cxQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-async-generator-functions": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.7.tgz", + "integrity": "sha512-PdxEpL71bJp1byMG0va5gwQcXHxuEYC/BgI/e88mGTtohbZN28O5Yit0Plkkm/dBzCF/BxmbNcses1RH1T+urA==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-remap-async-to-generator": "^7.22.20", + "@babel/plugin-syntax-async-generators": "^7.8.4" + } + }, + "@babel/plugin-transform-async-to-generator": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.23.3.tgz", + "integrity": "sha512-A7LFsKi4U4fomjqXJlZg/u0ft/n8/7n7lpffUP/ZULx/DtV9SGlNKZolHH6PE8Xl1ngCc0M11OaeZptXVkfKSw==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-remap-async-to-generator": "^7.22.20" + } + }, + "@babel/plugin-transform-block-scoped-functions": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.23.3.tgz", + "integrity": "sha512-vI+0sIaPIO6CNuM9Kk5VmXcMVRiOpDh7w2zZt9GXzmE/9KD70CUEVhvPR/etAeNK/FAEkhxQtXOzVF3EuRL41A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-block-scoping": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.4.tgz", + "integrity": "sha512-0QqbP6B6HOh7/8iNR4CQU2Th/bbRtBp4KS9vcaZd1fZ0wSh5Fyssg0UCIHwxh+ka+pNDREbVLQnHCMHKZfPwfw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-class-properties": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.23.3.tgz", + "integrity": "sha512-uM+AN8yCIjDPccsKGlw271xjJtGii+xQIF/uMPS8H15L12jZTsLfF4o5vNO7d/oUguOyfdikHGc/yi9ge4SGIg==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-class-static-block": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.23.4.tgz", + "integrity": "sha512-nsWu/1M+ggti1SOALj3hfx5FXzAY06fwPJsUZD4/A5e1bWi46VUIWtD+kOX6/IdhXGsXBWllLFDSnqSCdUNydQ==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + } + }, + "@babel/plugin-transform-classes": { + "version": "7.23.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.23.8.tgz", + "integrity": "sha512-yAYslGsY1bX6Knmg46RjiCiNSwJKv2IUC8qOdYKqMMr0491SXFhcHqOdRDeCRohOOIzwN/90C6mQ9qAKgrP7dg==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.20", + "@babel/helper-split-export-declaration": "^7.22.6", + "globals": "^11.1.0" + } + }, + "@babel/plugin-transform-computed-properties": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.23.3.tgz", + "integrity": "sha512-dTj83UVTLw/+nbiHqQSFdwO9CbTtwq1DsDqm3CUEtDrZNET5rT5E6bIdTlOftDTDLMYxvxHNEYO4B9SLl8SLZw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/template": "^7.22.15" + } + }, + "@babel/plugin-transform-destructuring": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.3.tgz", + "integrity": "sha512-n225npDqjDIr967cMScVKHXJs7rout1q+tt50inyBCPkyZ8KxeI6d+GIbSBTT/w/9WdlWDOej3V9HE5Lgk57gw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-dotall-regex": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.23.3.tgz", + "integrity": "sha512-vgnFYDHAKzFaTVp+mneDsIEbnJ2Np/9ng9iviHw3P/KVcgONxpNULEW/51Z/BaFojG2GI2GwwXck5uV1+1NOYQ==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-duplicate-keys": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.23.3.tgz", + "integrity": "sha512-RrqQ+BQmU3Oyav3J+7/myfvRCq7Tbz+kKLLshUmMwNlDHExbGL7ARhajvoBJEvc+fCguPPu887N+3RRXBVKZUA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-dynamic-import": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.23.4.tgz", + "integrity": "sha512-V6jIbLhdJK86MaLh4Jpghi8ho5fGzt3imHOBu/x0jlBaPYqDoWz4RDXjmMOfnh+JWNaQleEAByZLV0QzBT4YQQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + } + }, + "@babel/plugin-transform-exponentiation-operator": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.23.3.tgz", + "integrity": "sha512-5fhCsl1odX96u7ILKHBj4/Y8vipoqwsJMh4csSA8qFfxrZDEA4Ssku2DyNvMJSmZNOEBT750LfFPbtrnTP90BQ==", + "dev": true, + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-export-namespace-from": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.23.4.tgz", + "integrity": "sha512-GzuSBcKkx62dGzZI1WVgTWvkkz84FZO5TC5T8dl/Tht/rAla6Dg/Mz9Yhypg+ezVACf/rgDuQt3kbWEv7LdUDQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + } + }, + "@babel/plugin-transform-flow-strip-types": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.23.3.tgz", + "integrity": "sha512-26/pQTf9nQSNVJCrLB1IkHUKyPxR+lMrH2QDPG89+Znu9rAMbtrybdbWeE9bb7gzjmE5iXHEY+e0HUwM6Co93Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-flow": "^7.23.3" + } + }, + "@babel/plugin-transform-for-of": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.23.6.tgz", + "integrity": "sha512-aYH4ytZ0qSuBbpfhuofbg/e96oQ7U2w1Aw/UQmKT+1l39uEhUPoFS3fHevDc1G0OvewyDudfMKY1OulczHzWIw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + } + }, + "@babel/plugin-transform-function-name": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.23.3.tgz", + "integrity": "sha512-I1QXp1LxIvt8yLaib49dRW5Okt7Q4oaxao6tFVKS/anCdEOMtYwWVKoiOA1p34GOWIZjUK0E+zCp7+l1pfQyiw==", + "dev": true, + "requires": { + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-json-strings": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.23.4.tgz", + "integrity": "sha512-81nTOqM1dMwZ/aRXQ59zVubN9wHGqk6UtqRK+/q+ciXmRy8fSolhGVvG09HHRGo4l6fr/c4ZhXUQH0uFW7PZbg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-json-strings": "^7.8.3" + } + }, + "@babel/plugin-transform-literals": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.23.3.tgz", + "integrity": "sha512-wZ0PIXRxnwZvl9AYpqNUxpZ5BiTGrYt7kueGQ+N5FiQ7RCOD4cm8iShd6S6ggfVIWaJf2EMk8eRzAh52RfP4rQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-logical-assignment-operators": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.23.4.tgz", + "integrity": "sha512-Mc/ALf1rmZTP4JKKEhUwiORU+vcfarFVLfcFiolKUo6sewoxSEgl36ak5t+4WamRsNr6nzjZXQjM35WsU+9vbg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + } + }, + "@babel/plugin-transform-member-expression-literals": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.23.3.tgz", + "integrity": "sha512-sC3LdDBDi5x96LA+Ytekz2ZPk8i/Ck+DEuDbRAll5rknJ5XRTSaPKEYwomLcs1AA8wg9b3KjIQRsnApj+q51Ag==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-modules-amd": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.23.3.tgz", + "integrity": "sha512-vJYQGxeKM4t8hYCKVBlZX/gtIY2I7mRGFNcm85sgXGMTBcoV3QdVtdpbcWEbzbfUIUZKwvgFT82mRvaQIebZzw==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.3.tgz", + "integrity": "sha512-aVS0F65LKsdNOtcz6FRCpE4OgsP2OFnW46qNxNIX9h3wuzaNcSQsJysuMwqSibC98HPrf2vCgtxKNwS0DAlgcA==", + "requires": { + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-simple-access": "^7.22.5" + } + }, + "@babel/plugin-transform-modules-systemjs": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.3.tgz", + "integrity": "sha512-ZxyKGTkF9xT9YJuKQRo19ewf3pXpopuYQd8cDXqNzc3mUNbOME0RKMoZxviQk74hwzfQsEe66dE92MaZbdHKNQ==", + "dev": true, + "requires": { + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20" + } + }, + "@babel/plugin-transform-modules-umd": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.23.3.tgz", + "integrity": "sha512-zHsy9iXX2nIsCBFPud3jKn1IRPWg3Ing1qOZgeKV39m1ZgIdpJqvlWVeiHBZC6ITRG0MfskhYe9cLgntfSFPIg==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz", + "integrity": "sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-new-target": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.23.3.tgz", + "integrity": "sha512-YJ3xKqtJMAT5/TIZnpAR3I+K+WaDowYbN3xyxI8zxx/Gsypwf9B9h0VB+1Nh6ACAAPRS5NSRje0uVv5i79HYGQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.23.4.tgz", + "integrity": "sha512-jHE9EVVqHKAQx+VePv5LLGHjmHSJR76vawFPTdlxR/LVJPfOEGxREQwQfjuZEOPTwG92X3LINSh3M40Rv4zpVA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + } + }, + "@babel/plugin-transform-numeric-separator": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.23.4.tgz", + "integrity": "sha512-mps6auzgwjRrwKEZA05cOwuDc9FAzoyFS4ZsG/8F43bTLf/TgkJg7QXOrPO1JO599iA3qgK9MXdMGOEC8O1h6Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + } + }, + "@babel/plugin-transform-object-rest-spread": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.23.4.tgz", + "integrity": "sha512-9x9K1YyeQVw0iOXJlIzwm8ltobIIv7j2iLyP2jIhEbqPRQ7ScNgwQufU2I0Gq11VjyG4gI4yMXt2VFags+1N3g==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.23.3", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.23.3" + } + }, + "@babel/plugin-transform-object-super": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.23.3.tgz", + "integrity": "sha512-BwQ8q0x2JG+3lxCVFohg+KbQM7plfpBwThdW9A6TMtWwLsbDA01Ek2Zb/AgDN39BiZsExm4qrXxjk+P1/fzGrA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.20" + } + }, + "@babel/plugin-transform-optional-catch-binding": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.23.4.tgz", + "integrity": "sha512-XIq8t0rJPHf6Wvmbn9nFxU6ao4c7WhghTR5WyV8SrJfUFzyxhCm4nhC+iAp3HFhbAKLfYpgzhJ6t4XCtVwqO5A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + } + }, + "@babel/plugin-transform-optional-chaining": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.4.tgz", + "integrity": "sha512-ZU8y5zWOfjM5vZ+asjgAPwDaBjJzgufjES89Rs4Lpq63O300R/kOz30WCLo6BxxX6QVEilwSlpClnG5cZaikTA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + } + }, + "@babel/plugin-transform-parameters": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.23.3.tgz", + "integrity": "sha512-09lMt6UsUb3/34BbECKVbVwrT9bO6lILWln237z7sLaWnMsTi7Yc9fhX5DLpkJzAGfaReXI22wP41SZmnAA3Vw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-private-methods": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.23.3.tgz", + "integrity": "sha512-UzqRcRtWsDMTLrRWFvUBDwmw06tCQH9Rl1uAjfh6ijMSmGYQ+fpdB+cnqRC8EMh5tuuxSv0/TejGL+7vyj+50g==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-private-property-in-object": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.23.4.tgz", + "integrity": "sha512-9G3K1YqTq3F4Vt88Djx1UZ79PDyj+yKRnUy7cZGSMe+a7jkwD259uKKuUzQlPkGam7R+8RJwh5z4xO27fA1o2A==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + } + }, + "@babel/plugin-transform-property-literals": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.23.3.tgz", + "integrity": "sha512-jR3Jn3y7cZp4oEWPFAlRsSWjxKe4PZILGBSd4nis1TsC5qeSpb+nrtihJuDhNI7QHiVbUaiXa0X2RZY3/TI6Nw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-regenerator": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.23.3.tgz", + "integrity": "sha512-KP+75h0KghBMcVpuKisx3XTu9Ncut8Q8TuvGO4IhY+9D5DFEckQefOuIsB/gQ2tG71lCke4NMrtIPS8pOj18BQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "regenerator-transform": "^0.15.2" + } + }, + "@babel/plugin-transform-reserved-words": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.23.3.tgz", + "integrity": "sha512-QnNTazY54YqgGxwIexMZva9gqbPa15t/x9VS+0fsEFWplwVpXYZivtgl43Z1vMpc1bdPP2PP8siFeVcnFvA3Cg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-shorthand-properties": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.23.3.tgz", + "integrity": "sha512-ED2fgqZLmexWiN+YNFX26fx4gh5qHDhn1O2gvEhreLW2iI63Sqm4llRLCXALKrCnbN4Jy0VcMQZl/SAzqug/jg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-spread": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.23.3.tgz", + "integrity": "sha512-VvfVYlrlBVu+77xVTOAoxQ6mZbnIq5FM0aGBSFEcIh03qHf+zNqA4DC/3XMUozTg7bZV3e3mZQ0i13VB6v5yUg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + } + }, + "@babel/plugin-transform-sticky-regex": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.23.3.tgz", + "integrity": "sha512-HZOyN9g+rtvnOU3Yh7kSxXrKbzgrm5X4GncPY1QOquu7epga5MxKHVpYu2hvQnry/H+JjckSYRb93iNfsioAGg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-template-literals": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.23.3.tgz", + "integrity": "sha512-Flok06AYNp7GV2oJPZZcP9vZdszev6vPBkHLwxwSpaIqx75wn6mUd3UFWsSsA0l8nXAKkyCmL/sR02m8RYGeHg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-typeof-symbol": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.23.3.tgz", + "integrity": "sha512-4t15ViVnaFdrPC74be1gXBSMzXk3B4Us9lP7uLRQHTFpV5Dvt33pn+2MyyNxmN3VTTm3oTrZVMUmuw3oBnQ2oQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-typescript": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.23.6.tgz", + "integrity": "sha512-6cBG5mBvUu4VUD04OHKnYzbuHNP8huDsD3EDqqpIpsswTDoqHCjLoHb6+QgsV1WsT2nipRqCPgxD3LXnEO7XfA==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.23.6", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-typescript": "^7.23.3" + } + }, + "@babel/plugin-transform-unicode-escapes": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.23.3.tgz", + "integrity": "sha512-OMCUx/bU6ChE3r4+ZdylEqAjaQgHAgipgW8nsCfu5pGqDcFytVd91AwRvUJSBZDz0exPGgnjoqhgRYLRjFZc9Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-unicode-property-regex": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.23.3.tgz", + "integrity": "sha512-KcLIm+pDZkWZQAFJ9pdfmh89EwVfmNovFBcXko8szpBeF8z68kWIPeKlmSOkT9BXJxs2C0uk+5LxoxIv62MROA==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-unicode-regex": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.23.3.tgz", + "integrity": "sha512-wMHpNA4x2cIA32b/ci3AfwNgheiva2W0WUKWTK7vBHBhDKfPsc5cFGNWm69WBqpwd86u1qwZ9PWevKqm1A3yAw==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-unicode-sets-regex": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.23.3.tgz", + "integrity": "sha512-W7lliA/v9bNR83Qc3q1ip9CQMZ09CcHDbHfbLRDNuAhn1Mvkr1ZNF7hPmztMQvtTGVLJ9m8IZqWsTkXOml8dbw==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/preset-env": { + "version": "7.23.8", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.23.8.tgz", + "integrity": "sha512-lFlpmkApLkEP6woIKprO6DO60RImpatTQKtz4sUcDjVcK8M8mQ4sZsuxaTMNOZf0sqAq/ReYW1ZBHnOQwKpLWA==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.23.5", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-option": "^7.23.5", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.23.3", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.23.3", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.23.7", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.23.3", + "@babel/plugin-syntax-import-attributes": "^7.23.3", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.23.3", + "@babel/plugin-transform-async-generator-functions": "^7.23.7", + "@babel/plugin-transform-async-to-generator": "^7.23.3", + "@babel/plugin-transform-block-scoped-functions": "^7.23.3", + "@babel/plugin-transform-block-scoping": "^7.23.4", + "@babel/plugin-transform-class-properties": "^7.23.3", + "@babel/plugin-transform-class-static-block": "^7.23.4", + "@babel/plugin-transform-classes": "^7.23.8", + "@babel/plugin-transform-computed-properties": "^7.23.3", + "@babel/plugin-transform-destructuring": "^7.23.3", + "@babel/plugin-transform-dotall-regex": "^7.23.3", + "@babel/plugin-transform-duplicate-keys": "^7.23.3", + "@babel/plugin-transform-dynamic-import": "^7.23.4", + "@babel/plugin-transform-exponentiation-operator": "^7.23.3", + "@babel/plugin-transform-export-namespace-from": "^7.23.4", + "@babel/plugin-transform-for-of": "^7.23.6", + "@babel/plugin-transform-function-name": "^7.23.3", + "@babel/plugin-transform-json-strings": "^7.23.4", + "@babel/plugin-transform-literals": "^7.23.3", + "@babel/plugin-transform-logical-assignment-operators": "^7.23.4", + "@babel/plugin-transform-member-expression-literals": "^7.23.3", + "@babel/plugin-transform-modules-amd": "^7.23.3", + "@babel/plugin-transform-modules-commonjs": "^7.23.3", + "@babel/plugin-transform-modules-systemjs": "^7.23.3", + "@babel/plugin-transform-modules-umd": "^7.23.3", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5", + "@babel/plugin-transform-new-target": "^7.23.3", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.23.4", + "@babel/plugin-transform-numeric-separator": "^7.23.4", + "@babel/plugin-transform-object-rest-spread": "^7.23.4", + "@babel/plugin-transform-object-super": "^7.23.3", + "@babel/plugin-transform-optional-catch-binding": "^7.23.4", + "@babel/plugin-transform-optional-chaining": "^7.23.4", + "@babel/plugin-transform-parameters": "^7.23.3", + "@babel/plugin-transform-private-methods": "^7.23.3", + "@babel/plugin-transform-private-property-in-object": "^7.23.4", + "@babel/plugin-transform-property-literals": "^7.23.3", + "@babel/plugin-transform-regenerator": "^7.23.3", + "@babel/plugin-transform-reserved-words": "^7.23.3", + "@babel/plugin-transform-shorthand-properties": "^7.23.3", + "@babel/plugin-transform-spread": "^7.23.3", + "@babel/plugin-transform-sticky-regex": "^7.23.3", + "@babel/plugin-transform-template-literals": "^7.23.3", + "@babel/plugin-transform-typeof-symbol": "^7.23.3", + "@babel/plugin-transform-unicode-escapes": "^7.23.3", + "@babel/plugin-transform-unicode-property-regex": "^7.23.3", + "@babel/plugin-transform-unicode-regex": "^7.23.3", + "@babel/plugin-transform-unicode-sets-regex": "^7.23.3", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.7", + "babel-plugin-polyfill-corejs3": "^0.8.7", + "babel-plugin-polyfill-regenerator": "^0.5.4", + "core-js-compat": "^3.31.0", + "semver": "^6.3.1" + } + }, + "@babel/preset-flow": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.23.3.tgz", + "integrity": "sha512-7yn6hl8RIv+KNk6iIrGZ+D06VhVY35wLVf23Cz/mMu1zOr7u4MMP4j0nZ9tLf8+4ZFpnib8cFYgB/oYg9hfswA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-option": "^7.22.15", + "@babel/plugin-transform-flow-strip-types": "^7.23.3" + } + }, + "@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + } + }, + "@babel/preset-typescript": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.23.3.tgz", + "integrity": "sha512-17oIGVlqz6CchO9RFYn5U6ZpWRZIngayYCtrPRSgANSwC2V1Jb+iP74nVxzzXJte8b8BYxrL1yY96xfhTBrNNQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-option": "^7.22.15", + "@babel/plugin-syntax-jsx": "^7.23.3", + "@babel/plugin-transform-modules-commonjs": "^7.23.3", + "@babel/plugin-transform-typescript": "^7.23.3" + } + }, + "@babel/register": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.23.7.tgz", + "integrity": "sha512-EjJeB6+kvpk+Y5DAkEAmbOBEFkh9OASx0huoEkqYTFxAZHzOAX2Oh5uwAUuL2rUddqfM0SA+KPXV2TbzoZ2kvQ==", + "dev": true, + "requires": { + "clone-deep": "^4.0.1", + "find-cache-dir": "^2.0.0", + "make-dir": "^2.1.0", + "pirates": "^4.0.6", + "source-map-support": "^0.5.16" + }, + "dependencies": { + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + }, + "semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true + } + } + }, + "@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", + "dev": true + }, + "@babel/runtime": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz", + "integrity": "sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==", + "requires": { + "regenerator-runtime": "^0.13.11" + } + }, + "@babel/template": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "requires": { + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" + } + }, + "@babel/traverse": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.7.tgz", + "integrity": "sha512-tY3mM8rH9jM0YHFGyfC0/xf+SB5eKUu7HPj7/k3fpi9dAlsMc5YbQvDi0Sh2QTPXqMhyaAtzAr807TIyfQrmyg==", + "requires": { + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.6", + "@babel/types": "^7.23.6", + "debug": "^4.3.1", + "globals": "^11.1.0" + } + }, + "@babel/types": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.6.tgz", + "integrity": "sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==", + "requires": { + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + } + }, + "@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "dev": true, + "optional": true + }, + "@ctrl/tinycolor": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.0.tgz", + "integrity": "sha512-/Z3l6pXthq0JvMYdUFyX9j0MaCltlIn6mfh9jLyQwg5aPKxkyNa0PTHtU1AlFXLNk55ZuAeJRcpvq+tmLfKmaQ==" + }, + "@cubejs-client/core": { + "version": "0.31.63", + "resolved": "https://registry.npmjs.org/@cubejs-client/core/-/core-0.31.63.tgz", + "integrity": "sha512-NFlceV9G2HbFxGqTIjAqS43szRwEJDVzcfuWm/xwlAT6fU4OvZKdDXieKhaxLl38fh64m4VZefej0Mh5jwCmzQ==", + "requires": { + "@babel/runtime": "^7.1.2", + "core-js": "^3.6.5", + "cross-fetch": "^3.0.2", + "dayjs": "^1.10.4", + "ramda": "^0.27.2", + "url-search-params-polyfill": "^7.0.0", + "uuid": "^8.3.2" + }, + "dependencies": { + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" + } + } + }, + "@cubejs-client/vue3": { + "version": "0.31.63", + "resolved": "https://registry.npmjs.org/@cubejs-client/vue3/-/vue3-0.31.63.tgz", + "integrity": "sha512-3s2AHzavz6wudNVW7fhBtRsj0LpF6AoBRCzWm0eefMYHqxYK2ShbVEhz+c2oCM8Fri9vt7ZZt4X+70V5iPJTWw==", + "requires": { + "@cubejs-client/core": "^0.31.63", + "@vue/compiler-sfc": "^3.0.11", + "core-js": "^3.6.5", + "flush-promises": "^1.0.2", + "ramda": "^0.27.0", + "vue-loader": "^16.2.0" + } + }, + "@cypress/request": { + "version": "2.88.11", + "resolved": "https://registry.npmjs.org/@cypress/request/-/request-2.88.11.tgz", + "integrity": "sha512-M83/wfQ1EkspjkE2lNWNV5ui2Cv7UCv1swW1DqljahbzLVWltcsexQh8jYtuS/vzFXP+HySntGM83ZXA9fn17w==", + "dev": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "http-signature": "~1.3.6", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "performance-now": "^2.1.0", + "qs": "~6.10.3", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^8.3.2" + }, + "dependencies": { + "qs": { + "version": "6.10.4", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.4.tgz", + "integrity": "sha512-OQiU+C+Ds5qiH91qh/mg0w+8nwQuLjM4F4M/PbmhDOoYehPh+Fb0bDjtR1sOvy7YKxvj28Y/M0PhP5uVX0kB+g==", + "dev": true, + "requires": { + "side-channel": "^1.0.4" + } + }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true + } + } + }, + "@cypress/xvfb": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@cypress/xvfb/-/xvfb-1.2.4.tgz", + "integrity": "sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==", + "dev": true, + "requires": { + "debug": "^3.1.0", + "lodash.once": "^4.1.1" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "@dash14/svg-pan-zoom": { + "version": "3.6.9", + "resolved": "https://registry.npmjs.org/@dash14/svg-pan-zoom/-/svg-pan-zoom-3.6.9.tgz", + "integrity": "sha512-6u+KTQec+9+3bRdk2mReix8AGsp2mB40cw0iYfQQzo22QBkeCNpXl2amnfwQzK7xB9oH/62Wvf2z7l6l2w+csA==" + }, + "@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "dev": true + }, + "@element-plus/icons-vue": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@element-plus/icons-vue/-/icons-vue-2.1.0.tgz", + "integrity": "sha512-PSBn3elNoanENc1vnCfh+3WA9fimRC7n+fWkf3rE5jvv+aBohNHABC/KAR5KWPecxWxDTVT1ERpRbOMRcOV/vA==", + "requires": {} + }, + "@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz", + "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==", + "dev": true, + "requires": {} + }, + "@esbuild/android-arm": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.17.tgz", + "integrity": "sha512-wHsmJG/dnL3OkpAcwbgoBTTMHVi4Uyou3F5mf58ZtmUyIKfcdA7TROav/6tCzET4A3QW2Q2FC+eFneMU+iyOxg==", + "optional": true + }, + "@esbuild/android-arm64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.17.tgz", + "integrity": "sha512-9np+YYdNDed5+Jgr1TdWBsozZ85U1Oa3xW0c7TWqH0y2aGghXtZsuT8nYRbzOMcl0bXZXjOGbksoTtVOlWrRZg==", + "optional": true + }, + "@esbuild/android-x64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.17.tgz", + "integrity": "sha512-O+FeWB/+xya0aLg23hHEM2E3hbfwZzjqumKMSIqcHbNvDa+dza2D0yLuymRBQQnC34CWrsJUXyH2MG5VnLd6uw==", + "optional": true + }, + "@esbuild/darwin-arm64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.17.tgz", + "integrity": "sha512-M9uJ9VSB1oli2BE/dJs3zVr9kcCBBsE883prage1NWz6pBS++1oNn/7soPNS3+1DGj0FrkSvnED4Bmlu1VAE9g==", + "optional": true + }, + "@esbuild/darwin-x64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.17.tgz", + "integrity": "sha512-XDre+J5YeIJDMfp3n0279DFNrGCXlxOuGsWIkRb1NThMZ0BsrWXoTg23Jer7fEXQ9Ye5QjrvXpxnhzl3bHtk0g==", + "optional": true + }, + "@esbuild/freebsd-arm64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.17.tgz", + "integrity": "sha512-cjTzGa3QlNfERa0+ptykyxs5A6FEUQQF0MuilYXYBGdBxD3vxJcKnzDlhDCa1VAJCmAxed6mYhA2KaJIbtiNuQ==", + "optional": true + }, + "@esbuild/freebsd-x64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.17.tgz", + "integrity": "sha512-sOxEvR8d7V7Kw8QqzxWc7bFfnWnGdaFBut1dRUYtu+EIRXefBc/eIsiUiShnW0hM3FmQ5Zf27suDuHsKgZ5QrA==", + "optional": true + }, + "@esbuild/linux-arm": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.17.tgz", + "integrity": "sha512-2d3Lw6wkwgSLC2fIvXKoMNGVaeY8qdN0IC3rfuVxJp89CRfA3e3VqWifGDfuakPmp90+ZirmTfye1n4ncjv2lg==", + "optional": true + }, + "@esbuild/linux-arm64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.17.tgz", + "integrity": "sha512-c9w3tE7qA3CYWjT+M3BMbwMt+0JYOp3vCMKgVBrCl1nwjAlOMYzEo+gG7QaZ9AtqZFj5MbUc885wuBBmu6aADQ==", + "optional": true + }, + "@esbuild/linux-ia32": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.17.tgz", + "integrity": "sha512-1DS9F966pn5pPnqXYz16dQqWIB0dmDfAQZd6jSSpiT9eX1NzKh07J6VKR3AoXXXEk6CqZMojiVDSZi1SlmKVdg==", + "optional": true + }, + "@esbuild/linux-loong64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.17.tgz", + "integrity": "sha512-EvLsxCk6ZF0fpCB6w6eOI2Fc8KW5N6sHlIovNe8uOFObL2O+Mr0bflPHyHwLT6rwMg9r77WOAWb2FqCQrVnwFg==", + "optional": true + }, + "@esbuild/linux-mips64el": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.17.tgz", + "integrity": "sha512-e0bIdHA5p6l+lwqTE36NAW5hHtw2tNRmHlGBygZC14QObsA3bD4C6sXLJjvnDIjSKhW1/0S3eDy+QmX/uZWEYQ==", + "optional": true + }, + "@esbuild/linux-ppc64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.17.tgz", + "integrity": "sha512-BAAilJ0M5O2uMxHYGjFKn4nJKF6fNCdP1E0o5t5fvMYYzeIqy2JdAP88Az5LHt9qBoUa4tDaRpfWt21ep5/WqQ==", + "optional": true + }, + "@esbuild/linux-riscv64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.17.tgz", + "integrity": "sha512-Wh/HW2MPnC3b8BqRSIme/9Zhab36PPH+3zam5pqGRH4pE+4xTrVLx2+XdGp6fVS3L2x+DrsIcsbMleex8fbE6g==", + "optional": true + }, + "@esbuild/linux-s390x": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.17.tgz", + "integrity": "sha512-j/34jAl3ul3PNcK3pfI0NSlBANduT2UO5kZ7FCaK33XFv3chDhICLY8wJJWIhiQ+YNdQ9dxqQctRg2bvrMlYgg==", + "optional": true + }, + "@esbuild/linux-x64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.17.tgz", + "integrity": "sha512-QM50vJ/y+8I60qEmFxMoxIx4de03pGo2HwxdBeFd4nMh364X6TIBZ6VQ5UQmPbQWUVWHWws5MmJXlHAXvJEmpQ==", + "optional": true + }, + "@esbuild/netbsd-x64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.17.tgz", + "integrity": "sha512-/jGlhWR7Sj9JPZHzXyyMZ1RFMkNPjC6QIAan0sDOtIo2TYk3tZn5UDrkE0XgsTQCxWTTOcMPf9p6Rh2hXtl5TQ==", + "optional": true + }, + "@esbuild/openbsd-x64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.17.tgz", + "integrity": "sha512-rSEeYaGgyGGf4qZM2NonMhMOP/5EHp4u9ehFiBrg7stH6BYEEjlkVREuDEcQ0LfIl53OXLxNbfuIj7mr5m29TA==", + "optional": true + }, + "@esbuild/sunos-x64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.17.tgz", + "integrity": "sha512-Y7ZBbkLqlSgn4+zot4KUNYst0bFoO68tRgI6mY2FIM+b7ZbyNVtNbDP5y8qlu4/knZZ73fgJDlXID+ohY5zt5g==", + "optional": true + }, + "@esbuild/win32-arm64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.17.tgz", + "integrity": "sha512-bwPmTJsEQcbZk26oYpc4c/8PvTY3J5/QK8jM19DVlEsAB41M39aWovWoHtNm78sd6ip6prilxeHosPADXtEJFw==", + "optional": true + }, + "@esbuild/win32-ia32": { "version": "0.18.17", "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.17.tgz", "integrity": "sha512-H/XaPtPKli2MhW+3CQueo6Ni3Avggi6hP/YvgkEe1aSaxw+AeO8MFjq8DlgfTd9Iz4Yih3QCZI6YLMoyccnPRg==", "optional": true }, - "@esbuild/win32-x64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.17.tgz", - "integrity": "sha512-fGEb8f2BSA3CW7riJVurug65ACLuQAzKq0SSqkY2b2yHHH0MzDfbLyKIGzHwOI/gkHcxM/leuSW6D5w/LMNitA==", - "optional": true + "@esbuild/win32-x64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.17.tgz", + "integrity": "sha512-fGEb8f2BSA3CW7riJVurug65ACLuQAzKq0SSqkY2b2yHHH0MzDfbLyKIGzHwOI/gkHcxM/leuSW6D5w/LMNitA==", + "optional": true + }, + "@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "requires": { + "eslint-visitor-keys": "^3.3.0" + } + }, + "@eslint-community/regexpp": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.4.1.tgz", + "integrity": "sha512-BISJ6ZE4xQsuL/FmsyRaiffpq977bMlsKfGHTQrOGFErfByxIe6iZTxPf/00Zon9b9a7iUykfQwejN3s2ZW/Bw==" + }, + "@eslint/eslintrc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.1.tgz", + "integrity": "sha512-eFRmABvW2E5Ho6f5fHLqgena46rOj7r7OKHYfLElqcBfGFHHpjBhivyi5+jOEQuSpdc/1phIZJlbC2te+tZNIw==", + "requires": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.5.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "globals": { + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "requires": { + "type-fest": "^0.20.2" + } + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==" + } + } + }, + "@eslint/js": { + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.36.0.tgz", + "integrity": "sha512-lxJ9R5ygVm8ZWgYdUweoq5ownDlJ4upvoWmO4eLxBYHdMo+vZ/Rx0EN6MbKWDJOSUGrqJy2Gt+Dyv/VKml0fjg==" + }, + "@fal-works/esbuild-plugin-global-externals": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@fal-works/esbuild-plugin-global-externals/-/esbuild-plugin-global-externals-2.1.2.tgz", + "integrity": "sha512-cEee/Z+I12mZcFJshKcCqC8tuX5hG3s+d+9nZ3LabqKF1vKdF41B92pJVCBggjAGORAeOzyyDDKrZwIkLffeOQ==", + "dev": true + }, + "@floating-ui/core": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.5.3.tgz", + "integrity": "sha512-O0WKDOo0yhJuugCx6trZQj5jVJ9yR0ystG2JaNAemYUWce+pmM6WUEFIibnWyEJKdrDxhm75NoSRME35FNaM/Q==", + "requires": { + "@floating-ui/utils": "^0.2.0" + } + }, + "@floating-ui/dom": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.5.4.tgz", + "integrity": "sha512-jByEsHIY+eEdCjnTVu+E3ephzTOzkQ8hgUfGwos+bg7NlH33Zc5uO+QHz1mrQUOgIKKDD1RtS201P9NvAfq3XQ==", + "requires": { + "@floating-ui/core": "^1.5.3", + "@floating-ui/utils": "^0.2.0" + } + }, + "@floating-ui/react-dom": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.0.6.tgz", + "integrity": "sha512-IB8aCRFxr8nFkdYZgH+Otd9EVQPJoynxeFRGTB8voPoZMRWo8XjYuCRgpI1btvuKY69XMiLnW+ym7zoBHM90Rw==", + "dev": true, + "requires": { + "@floating-ui/dom": "^1.5.4" + } + }, + "@floating-ui/utils": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.1.tgz", + "integrity": "sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q==" + }, + "@formbricks/js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@formbricks/js/-/js-1.2.0.tgz", + "integrity": "sha512-bhQutlEHWnMHm54h6tc2VRM8lj/Rio0tT1L+zNjFv0Hcx4TamZ/967MyhGpY0LnJyqdr8Ck/+DtEWFSAOO5HEw==" + }, + "@hapi/hoek": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", + "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==", + "dev": true + }, + "@hapi/topo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "dev": true, + "requires": { + "@hapi/hoek": "^9.0.0" + } + }, + "@humanwhocodes/config-array": { + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", + "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", + "requires": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + } + }, + "@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==" + }, + "@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==" + }, + "@interactjs/actions": { + "version": "1.10.17", + "resolved": "https://registry.npmjs.org/@interactjs/actions/-/actions-1.10.17.tgz", + "integrity": "sha512-wyB1ZqpaZy5gmz6VDqK9KWh98xKnFgL7VyLvxHODFi9V0IYX4HJAAOBlhtfze0D1R1f1cY+gqPDK+dLaHMlE+w==", + "requires": { + "@interactjs/interact": "1.10.17" + } + }, + "@interactjs/auto-scroll": { + "version": "1.10.17", + "resolved": "https://registry.npmjs.org/@interactjs/auto-scroll/-/auto-scroll-1.10.17.tgz", + "integrity": "sha512-IQcW7N3xOaoL8RnAGOGMk0Y2gue7L4S3BT6Id4VBBu8so163DtLiZVW6jXu9rKVntzbluaAeqNZlfAVyu3kIWg==", + "requires": { + "@interactjs/interact": "1.10.17" + } + }, + "@interactjs/auto-start": { + "version": "1.10.17", + "resolved": "https://registry.npmjs.org/@interactjs/auto-start/-/auto-start-1.10.17.tgz", + "integrity": "sha512-qYVxhAbYnwxjD/NLEegUoAST7WASJ4VmWNjsyWRx/js5Op+I4E2zteARIeZGgrutcGIXMCcQzhCMgE3PjOpbpw==", + "requires": { + "@interactjs/interact": "1.10.17" + } + }, + "@interactjs/core": { + "version": "1.10.17", + "resolved": "https://registry.npmjs.org/@interactjs/core/-/core-1.10.17.tgz", + "integrity": "sha512-rL9w+83HDRuXub8Ezqs+97CYLl/ne7bLT/sAeduUWaxYhsW9iOqBoob9JnkkCZOaOsYizWI1EWy0+fNc5ibtLQ==", + "requires": {} + }, + "@interactjs/dev-tools": { + "version": "1.10.17", + "resolved": "https://registry.npmjs.org/@interactjs/dev-tools/-/dev-tools-1.10.17.tgz", + "integrity": "sha512-Oi9nEw3FfSwkNmW+V0WwdHqvzEkVHc24mH1v5EjRn60sqgrGLK9nTQ+NSuqcnUY8GxC3TkyuxnsOodxiadIRmA==", + "requires": { + "@interactjs/interact": "1.10.17" + } + }, + "@interactjs/inertia": { + "version": "1.10.17", + "resolved": "https://registry.npmjs.org/@interactjs/inertia/-/inertia-1.10.17.tgz", + "integrity": "sha512-41vbYUjZIDCKt2/yhmjPrEW5+0uoL/hldFsll9pkvnLhmm12Xk0VXOlmR2zXKAmsTK3fJlKMyBYUX92qHLkyVQ==", + "requires": { + "@interactjs/interact": "1.10.17", + "@interactjs/offset": "1.10.17" + } + }, + "@interactjs/interact": { + "version": "1.10.17", + "resolved": "https://registry.npmjs.org/@interactjs/interact/-/interact-1.10.17.tgz", + "integrity": "sha512-NyKsf8EFudvdahBjPz1Gt5QnynVwa/2LUfBc2/w8QOnOBiyzUm0HLloJSaB8a50QbQkSWN243/Lgpd8GTMQvuQ==", + "requires": { + "@interactjs/core": "1.10.17", + "@interactjs/types": "1.10.17", + "@interactjs/utils": "1.10.17" + } + }, + "@interactjs/interactjs": { + "version": "1.10.17", + "resolved": "https://registry.npmjs.org/@interactjs/interactjs/-/interactjs-1.10.17.tgz", + "integrity": "sha512-hHmiukARbZhiM12zNKx0yQlFVl4C+NMeYNAYh6Mf9U3ZziQ47C+JEW8Gr7Zr/MxfNZyPu5nLKCpVQjh/JvBO9g==", + "requires": { + "@interactjs/actions": "1.10.17", + "@interactjs/auto-scroll": "1.10.17", + "@interactjs/auto-start": "1.10.17", + "@interactjs/core": "1.10.17", + "@interactjs/dev-tools": "1.10.17", + "@interactjs/inertia": "1.10.17", + "@interactjs/interact": "1.10.17", + "@interactjs/modifiers": "1.10.17", + "@interactjs/offset": "1.10.17", + "@interactjs/pointer-events": "1.10.17", + "@interactjs/reflow": "1.10.17", + "@interactjs/utils": "1.10.17" + } + }, + "@interactjs/modifiers": { + "version": "1.10.17", + "resolved": "https://registry.npmjs.org/@interactjs/modifiers/-/modifiers-1.10.17.tgz", + "integrity": "sha512-Dxw8kv9VBIxnhNvQncR6CKAGMzKXczLvuAUIdSPFYtyerX/XiDulJUqhR+jVKNp/WjF1DvdBxWo0kGGLbM84LQ==", + "requires": { + "@interactjs/interact": "1.10.17", + "@interactjs/snappers": "1.10.17" + } + }, + "@interactjs/offset": { + "version": "1.10.17", + "resolved": "https://registry.npmjs.org/@interactjs/offset/-/offset-1.10.17.tgz", + "integrity": "sha512-wWBnIQWgLrmJNTBbd/FdxHxAJjiXl/5ND8Jbw2DuP9gIGDxhFSdEt62Fgqimn9ICb8v8ycvSLObEmcvJF/8hQQ==", + "requires": { + "@interactjs/interact": "1.10.17" + } + }, + "@interactjs/pointer-events": { + "version": "1.10.17", + "resolved": "https://registry.npmjs.org/@interactjs/pointer-events/-/pointer-events-1.10.17.tgz", + "integrity": "sha512-VsfluouEKb8QRGyH6jQATCW+QdAd/3dkENS7rj2m+EcVUhz2Ob5mpMRopjALi4pwltMowqTfuJ4LtwMSX2G29A==", + "requires": { + "@interactjs/interact": "1.10.17" + } + }, + "@interactjs/reflow": { + "version": "1.10.17", + "resolved": "https://registry.npmjs.org/@interactjs/reflow/-/reflow-1.10.17.tgz", + "integrity": "sha512-ncpWP5k93FRQptEhjzPZsbuRRajd4rkW17lDavCrEjrDi/LHnYekWGqZTaFzfJ80n1x8xUm9ujDjxCTylNqEIA==", + "requires": { + "@interactjs/interact": "1.10.17" + } + }, + "@interactjs/snappers": { + "version": "1.10.17", + "resolved": "https://registry.npmjs.org/@interactjs/snappers/-/snappers-1.10.17.tgz", + "integrity": "sha512-m753DGsNOts797e3zDT6wqELoc+BlpIC1w+TyMyISRxU6n1RlS8Q6LHBGgwAgV79LHLaahv/a5haFF9H1VG0FQ==", + "requires": { + "@interactjs/interact": "1.10.17" + } + }, + "@interactjs/types": { + "version": "1.10.17", + "resolved": "https://registry.npmjs.org/@interactjs/types/-/types-1.10.17.tgz", + "integrity": "sha512-X2JpoM7xUw0p9Me0tMaI0HNfcF/Hd07ZZlzpnpEMpGerUZOLoyeThrV9P+CrBHxZrluWJrigJbcdqXliFd0YMA==" + }, + "@interactjs/utils": { + "version": "1.10.17", + "resolved": "https://registry.npmjs.org/@interactjs/utils/-/utils-1.10.17.tgz", + "integrity": "sha512-sZAW08CkqgvqRjUIaLRjScjObcCzN9D75yekLA21EClYAZIhi4A+GEt2z/WqOCOksTaEPLYmQyhkpXcboc0LhQ==" + }, + "@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "requires": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true + }, + "ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true + }, + "string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "requires": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + } + }, + "strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "requires": { + "ansi-regex": "^6.0.1" + } + }, + "wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "requires": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + } + } + } + }, + "@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "requires": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "dependencies": { + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + } + } + }, + "@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true + }, + "@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "requires": { + "@sinclair/typebox": "^0.27.8" + } + }, + "@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, + "requires": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "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 + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "requires": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "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 + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@jridgewell/gen-mapping": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", + "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "requires": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==" + }, + "@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==" + }, + "@jridgewell/source-map": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", + "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "requires": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "dependencies": { + "@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + } + } + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" + }, + "@jridgewell/trace-mapping": { + "version": "0.3.22", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz", + "integrity": "sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==", + "requires": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "@juggle/resize-observer": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@juggle/resize-observer/-/resize-observer-3.4.0.tgz", + "integrity": "sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==", + "dev": true + }, + "@koa/router": { + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/@koa/router/-/router-9.4.0.tgz", + "integrity": "sha512-dOOXgzqaDoHu5qqMEPLKEgLz5CeIA7q8+1W62mCvFVCOqeC71UoTGJ4u1xUSOpIl2J1x2pqrNULkFteUeZW3/A==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "http-errors": "^1.7.3", + "koa-compose": "^4.1.0", + "methods": "^1.1.2", + "path-to-regexp": "^6.1.0" + } + }, + "@linaria/core": { + "version": "4.2.9", + "resolved": "https://registry.npmjs.org/@linaria/core/-/core-4.2.9.tgz", + "integrity": "sha512-ELcu37VNVOT/PU0L6WDIN+aLzNFyJrqoBYT0CucGOCAmODbojUMCv8oJYRbWzA3N34w1t199dN4UFdfRWFG2rg==", + "requires": { + "@linaria/logger": "^4.0.0", + "@linaria/tags": "^4.3.4", + "@linaria/utils": "^4.3.3" + } + }, + "@linaria/logger": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@linaria/logger/-/logger-4.0.0.tgz", + "integrity": "sha512-YnBq0JlDWMEkTOK+tMo5yEVR0f5V//6qMLToGcLhTyM9g9i+IDFn51Z+5q2hLk7RdG4NBPgbcCXYi2w4RKsPeg==", + "requires": { + "debug": "^4.1.1", + "picocolors": "^1.0.0" + } + }, + "@linaria/tags": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/@linaria/tags/-/tags-4.3.5.tgz", + "integrity": "sha512-PgaIi8Vv89YOjc6rpKL/uPg2w4k0rAwAYxcqeXqzKqsEAste5rgB8xp1/KUOG0oAOkPd3MRL6Duj+m0ZwJ3g+g==", + "requires": { + "@babel/generator": "^7.20.4", + "@linaria/logger": "^4.0.0", + "@linaria/utils": "^4.3.4" + } + }, + "@linaria/utils": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/@linaria/utils/-/utils-4.3.4.tgz", + "integrity": "sha512-vt6WJG54n+KANaqxOfzIIU7aSfFHEWFbnGLsgxL7nASHqO0zezrNA2y2Rrp80zSeTW+wSpbmDM4uJyC9UW1qoA==", + "requires": { + "@babel/core": "^7.20.2", + "@babel/plugin-proposal-export-namespace-from": "^7.18.9", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-transform-modules-commonjs": "^7.19.6", + "@babel/traverse": "^7.20.1", + "@babel/types": "^7.20.2", + "@linaria/logger": "^4.0.0", + "babel-merge": "^3.0.0" + } + }, + "@loomhq/loom-embed": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@loomhq/loom-embed/-/loom-embed-1.5.0.tgz", + "integrity": "sha512-1Rilv+Ta39Rk2mEb8wzfLSpPhl6ax7kfLNnfYTAGK4mCJIxwQ1o/BY46QRbIpQT/SdfsFCvvNWa57hlEEaduGA==" + }, + "@mdx-js/react": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-2.3.0.tgz", + "integrity": "sha512-zQH//gdOmuu7nt2oJR29vFhDv88oGPmVw6BggmrHeMI+xgEkp1B2dX9/bMBSYtK0dyLX/aOmesKS09g222K1/g==", + "dev": true, + "requires": { + "@types/mdx": "^2.0.0", + "@types/react": ">=16" + } + }, + "@nangohq/frontend": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@nangohq/frontend/-/frontend-0.9.0.tgz", + "integrity": "sha512-LLM74Bs1LQ8LalN2zokC/6MEeNMmpGyFAsVTmg5xpeYWXsHG7B1qh4LAUDKWrRM9z9J8r5Y/+hEUv3WJtum1Rw==" + }, + "@ndelangen/get-tarball": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@ndelangen/get-tarball/-/get-tarball-3.0.9.tgz", + "integrity": "sha512-9JKTEik4vq+yGosHYhZ1tiH/3WpUS0Nh0kej4Agndhox8pAdWhEx5knFVRcb/ya9knCRCs1rPxNrSXTDdfVqpA==", + "dev": true, + "requires": { + "gunzip-maybe": "^1.4.2", + "pump": "^3.0.0", + "tar-fs": "^2.1.1" + } + }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==" + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, + "@octokit/auth-token": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz", + "integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==", + "requires": { + "@octokit/types": "^6.0.3" + } + }, + "@octokit/core": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz", + "integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==", + "requires": { + "@octokit/auth-token": "^2.4.4", + "@octokit/graphql": "^4.5.8", + "@octokit/request": "^5.6.3", + "@octokit/request-error": "^2.0.5", + "@octokit/types": "^6.0.3", + "before-after-hook": "^2.2.0", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/endpoint": { + "version": "6.0.12", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", + "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", + "requires": { + "@octokit/types": "^6.0.3", + "is-plain-object": "^5.0.0", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/graphql": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz", + "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==", + "requires": { + "@octokit/request": "^5.6.0", + "@octokit/types": "^6.0.3", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/openapi-types": { + "version": "12.11.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", + "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==" + }, + "@octokit/request": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz", + "integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==", + "requires": { + "@octokit/endpoint": "^6.0.1", + "@octokit/request-error": "^2.1.0", + "@octokit/types": "^6.16.1", + "is-plain-object": "^5.0.0", + "node-fetch": "^2.6.7", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/request-error": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", + "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", + "requires": { + "@octokit/types": "^6.0.3", + "deprecation": "^2.0.0", + "once": "^1.4.0" + } + }, + "@octokit/types": { + "version": "6.41.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", + "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", + "requires": { + "@octokit/openapi-types": "^12.11.0" + } + }, + "@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true + }, + "@popperjs/core": { + "version": "npm:@sxzz/popperjs-es@2.11.7", + "resolved": "https://registry.npmjs.org/@sxzz/popperjs-es/-/popperjs-es-2.11.7.tgz", + "integrity": "sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ==" + }, + "@radix-ui/number": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.0.1.tgz", + "integrity": "sha512-T5gIdVO2mmPW3NNhjNgEP3cqMXjXL9UbO0BzWcXfvdBs+BohbQxvd/K5hSVKmn9/lbTdsQVKbUcP5WLCwvUbBg==", + "dev": true, + "requires": { + "@babel/runtime": "^7.13.10" + } + }, + "@radix-ui/primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.0.1.tgz", + "integrity": "sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw==", + "dev": true, + "requires": { + "@babel/runtime": "^7.13.10" + } + }, + "@radix-ui/react-arrow": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.0.3.tgz", + "integrity": "sha512-wSP+pHsB/jQRaL6voubsQ/ZlrGBHHrOjmBnr19hxYgtS0WvAFwZhK2WP/YY5yF9uKECCEEDGxuLxq1NBK51wFA==", + "dev": true, + "requires": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-primitive": "1.0.3" + } + }, + "@radix-ui/react-collection": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.0.3.tgz", + "integrity": "sha512-3SzW+0PW7yBBoQlT8wNcGtaxaD0XSu0uLUFgrtHY08Acx05TaHaOmVLR73c0j/cqpDy53KBMO7s0dx2wmOIDIA==", + "dev": true, + "requires": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-slot": "1.0.2" + } + }, + "@radix-ui/react-compose-refs": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.1.tgz", + "integrity": "sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==", + "dev": true, + "requires": { + "@babel/runtime": "^7.13.10" + } + }, + "@radix-ui/react-context": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.0.1.tgz", + "integrity": "sha512-ebbrdFoYTcuZ0v4wG5tedGnp9tzcV8awzsxYph7gXUyvnNLuTIcCk1q17JEbnVhXAKG9oX3KtchwiMIAYp9NLg==", + "dev": true, + "requires": { + "@babel/runtime": "^7.13.10" + } + }, + "@radix-ui/react-direction": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.0.1.tgz", + "integrity": "sha512-RXcvnXgyvYvBEOhCBuddKecVkoMiI10Jcm5cTI7abJRAHYfFxeu+FBQs/DvdxSYucxR5mna0dNsL6QFlds5TMA==", + "dev": true, + "requires": { + "@babel/runtime": "^7.13.10" + } + }, + "@radix-ui/react-dismissable-layer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.4.tgz", + "integrity": "sha512-7UpBa/RKMoHJYjie1gkF1DlK8l1fdU/VKDpoS3rCCo8YBJR294GwcEHyxHw72yvphJ7ld0AXEcSLAzY2F/WyCg==", + "dev": true, + "requires": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-callback-ref": "1.0.1", + "@radix-ui/react-use-escape-keydown": "1.0.3" + } + }, + "@radix-ui/react-focus-guards": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.0.1.tgz", + "integrity": "sha512-Rect2dWbQ8waGzhMavsIbmSVCgYxkXLxxR3ZvCX79JOglzdEy4JXMb98lq4hPxUbLr77nP0UOGf4rcMU+s1pUA==", + "dev": true, + "requires": { + "@babel/runtime": "^7.13.10" + } + }, + "@radix-ui/react-focus-scope": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.3.tgz", + "integrity": "sha512-upXdPfqI4islj2CslyfUBNlaJCPybbqRHAi1KER7Isel9Q2AtSJ0zRBZv8mWQiFXD2nyAJ4BhC3yXgZ6kMBSrQ==", + "dev": true, + "requires": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-callback-ref": "1.0.1" + } + }, + "@radix-ui/react-id": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.0.1.tgz", + "integrity": "sha512-tI7sT/kqYp8p96yGWY1OAnLHrqDgzHefRBKQ2YAkBS5ja7QLcZ9Z/uY7bEjPUatf8RomoXM8/1sMj1IJaE5UzQ==", + "dev": true, + "requires": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-use-layout-effect": "1.0.1" + } + }, + "@radix-ui/react-popper": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.1.2.tgz", + "integrity": "sha512-1CnGGfFi/bbqtJZZ0P/NQY20xdG3E0LALJaLUEoKwPLwl6PPPfbeiCqMVQnhoFRAxjJj4RpBRJzDmUgsex2tSg==", + "dev": true, + "requires": { + "@babel/runtime": "^7.13.10", + "@floating-ui/react-dom": "^2.0.0", + "@radix-ui/react-arrow": "1.0.3", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-callback-ref": "1.0.1", + "@radix-ui/react-use-layout-effect": "1.0.1", + "@radix-ui/react-use-rect": "1.0.1", + "@radix-ui/react-use-size": "1.0.1", + "@radix-ui/rect": "1.0.1" + } + }, + "@radix-ui/react-portal": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.0.3.tgz", + "integrity": "sha512-xLYZeHrWoPmA5mEKEfZZevoVRK/Q43GfzRXkWV6qawIWWK8t6ifIiLQdd7rmQ4Vk1bmI21XhqF9BN3jWf+phpA==", + "dev": true, + "requires": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-primitive": "1.0.3" + } + }, + "@radix-ui/react-primitive": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-1.0.3.tgz", + "integrity": "sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==", + "dev": true, + "requires": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-slot": "1.0.2" + } + }, + "@radix-ui/react-roving-focus": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.0.4.tgz", + "integrity": "sha512-2mUg5Mgcu001VkGy+FfzZyzbmuUWzgWkj3rvv4yu+mLw03+mTzbxZHvfcGyFp2b8EkQeMkpRQ5FiA2Vr2O6TeQ==", + "dev": true, + "requires": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-collection": "1.0.3", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-direction": "1.0.1", + "@radix-ui/react-id": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-callback-ref": "1.0.1", + "@radix-ui/react-use-controllable-state": "1.0.1" + } + }, + "@radix-ui/react-select": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-1.2.2.tgz", + "integrity": "sha512-zI7McXr8fNaSrUY9mZe4x/HC0jTLY9fWNhO1oLWYMQGDXuV4UCivIGTxwioSzO0ZCYX9iSLyWmAh/1TOmX3Cnw==", + "dev": true, + "requires": { + "@babel/runtime": "^7.13.10", + "@radix-ui/number": "1.0.1", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-collection": "1.0.3", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-direction": "1.0.1", + "@radix-ui/react-dismissable-layer": "1.0.4", + "@radix-ui/react-focus-guards": "1.0.1", + "@radix-ui/react-focus-scope": "1.0.3", + "@radix-ui/react-id": "1.0.1", + "@radix-ui/react-popper": "1.1.2", + "@radix-ui/react-portal": "1.0.3", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-slot": "1.0.2", + "@radix-ui/react-use-callback-ref": "1.0.1", + "@radix-ui/react-use-controllable-state": "1.0.1", + "@radix-ui/react-use-layout-effect": "1.0.1", + "@radix-ui/react-use-previous": "1.0.1", + "@radix-ui/react-visually-hidden": "1.0.3", + "aria-hidden": "^1.1.1", + "react-remove-scroll": "2.5.5" + } + }, + "@radix-ui/react-separator": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.0.3.tgz", + "integrity": "sha512-itYmTy/kokS21aiV5+Z56MZB54KrhPgn6eHDKkFeOLR34HMN2s8PaN47qZZAGnvupcjxHaFZnW4pQEh0BvvVuw==", + "dev": true, + "requires": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-primitive": "1.0.3" + } + }, + "@radix-ui/react-slot": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz", + "integrity": "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==", + "dev": true, + "requires": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-compose-refs": "1.0.1" + } + }, + "@radix-ui/react-toggle": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-toggle/-/react-toggle-1.0.3.tgz", + "integrity": "sha512-Pkqg3+Bc98ftZGsl60CLANXQBBQ4W3mTFS9EJvNxKMZ7magklKV69/id1mlAlOFDDfHvlCms0fx8fA4CMKDJHg==", + "dev": true, + "requires": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-controllable-state": "1.0.1" + } + }, + "@radix-ui/react-toggle-group": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-toggle-group/-/react-toggle-group-1.0.4.tgz", + "integrity": "sha512-Uaj/M/cMyiyT9Bx6fOZO0SAG4Cls0GptBWiBmBxofmDbNVnYYoyRWj/2M/6VCi/7qcXFWnHhRUfdfZFvvkuu8A==", + "dev": true, + "requires": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-direction": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-roving-focus": "1.0.4", + "@radix-ui/react-toggle": "1.0.3", + "@radix-ui/react-use-controllable-state": "1.0.1" + } + }, + "@radix-ui/react-toolbar": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-toolbar/-/react-toolbar-1.0.4.tgz", + "integrity": "sha512-tBgmM/O7a07xbaEkYJWYTXkIdU/1pW4/KZORR43toC/4XWyBCURK0ei9kMUdp+gTPPKBgYLxXmRSH1EVcIDp8Q==", + "dev": true, + "requires": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-direction": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-roving-focus": "1.0.4", + "@radix-ui/react-separator": "1.0.3", + "@radix-ui/react-toggle-group": "1.0.4" + } + }, + "@radix-ui/react-use-callback-ref": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.1.tgz", + "integrity": "sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ==", + "dev": true, + "requires": { + "@babel/runtime": "^7.13.10" + } + }, + "@radix-ui/react-use-controllable-state": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.0.1.tgz", + "integrity": "sha512-Svl5GY5FQeN758fWKrjM6Qb7asvXeiZltlT4U2gVfl8Gx5UAv2sMR0LWo8yhsIZh2oQ0eFdZ59aoOOMV7b47VA==", + "dev": true, + "requires": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-use-callback-ref": "1.0.1" + } + }, + "@radix-ui/react-use-escape-keydown": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.0.3.tgz", + "integrity": "sha512-vyL82j40hcFicA+M4Ex7hVkB9vHgSse1ZWomAqV2Je3RleKGO5iM8KMOEtfoSB0PnIelMd2lATjTGMYqN5ylTg==", + "dev": true, + "requires": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-use-callback-ref": "1.0.1" + } + }, + "@radix-ui/react-use-layout-effect": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.0.1.tgz", + "integrity": "sha512-v/5RegiJWYdoCvMnITBkNNx6bCj20fiaJnWtRkU18yITptraXjffz5Qbn05uOiQnOvi+dbkznkoaMltz1GnszQ==", + "dev": true, + "requires": { + "@babel/runtime": "^7.13.10" + } + }, + "@radix-ui/react-use-previous": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.0.1.tgz", + "integrity": "sha512-cV5La9DPwiQ7S0gf/0qiD6YgNqM5Fk97Kdrlc5yBcrF3jyEZQwm7vYFqMo4IfeHgJXsRaMvLABFtd0OVEmZhDw==", + "dev": true, + "requires": { + "@babel/runtime": "^7.13.10" + } + }, + "@radix-ui/react-use-rect": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.0.1.tgz", + "integrity": "sha512-Cq5DLuSiuYVKNU8orzJMbl15TXilTnJKUCltMVQg53BQOF1/C5toAaGrowkgksdBQ9H+SRL23g0HDmg9tvmxXw==", + "dev": true, + "requires": { + "@babel/runtime": "^7.13.10", + "@radix-ui/rect": "1.0.1" + } + }, + "@radix-ui/react-use-size": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.0.1.tgz", + "integrity": "sha512-ibay+VqrgcaI6veAojjofPATwledXiSmX+C0KrBk/xgpX9rBzPV3OsfwlhQdUOFbh+LKQorLYT+xTXW9V8yd0g==", + "dev": true, + "requires": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-use-layout-effect": "1.0.1" + } + }, + "@radix-ui/react-visually-hidden": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.0.3.tgz", + "integrity": "sha512-D4w41yN5YRKtu464TLnByKzMDG/JlMPHtfZgQAu9v6mNakUqGUI9vUrfQKz8NK41VMm/xbZbh76NUTVtIYqOMA==", + "dev": true, + "requires": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-primitive": "1.0.3" + } + }, + "@radix-ui/rect": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.0.1.tgz", + "integrity": "sha512-fyrgCaedtvMg9NK3en0pnOYJdtfwxUcNolezkNPUsoX57X8oQk+NkqcvzHXD2uKNij6GXmWU9NDru2IWjrO4BQ==", + "dev": true, + "requires": { + "@babel/runtime": "^7.13.10" + } + }, + "@remirror/core-constants": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@remirror/core-constants/-/core-constants-2.0.1.tgz", + "integrity": "sha512-ZR4aihtnnT9lMbhh5DEbsriJRlukRXmLZe7HmM+6ufJNNUDoazc75UX26xbgQlNUqgAqMcUdGFAnPc1JwgAdLQ==", + "requires": { + "@babel/runtime": "^7.21.0" + } + }, + "@remirror/core-helpers": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@remirror/core-helpers/-/core-helpers-2.0.3.tgz", + "integrity": "sha512-LqIPF4stGG69l9qu/FFicv9d9B+YaItzgDMC5A0CEvDQfKkGD3BfabLmfpnuWbsc06oKGdTduilgWcALLZoYLg==", + "requires": { + "@babel/runtime": "^7.21.0", + "@linaria/core": "4.2.9", + "@remirror/core-constants": "^2.0.1", + "@remirror/types": "^1.0.1", + "@types/object.omit": "^3.0.0", + "@types/object.pick": "^1.3.2", + "@types/throttle-debounce": "^2.1.0", + "case-anything": "^2.1.10", + "dash-get": "^1.0.2", + "deepmerge": "^4.3.1", + "fast-deep-equal": "^3.1.3", + "make-error": "^1.3.6", + "object.omit": "^3.0.0", + "object.pick": "^1.3.0", + "throttle-debounce": "^3.0.1" + } + }, + "@remirror/types": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@remirror/types/-/types-1.0.1.tgz", + "integrity": "sha512-VlZQxwGnt1jtQ18D6JqdIF+uFZo525WEqrfp9BOc3COPpK4+AWCgdnAWL+ho6imWcoINlGjR/+3b6y5C1vBVEA==", + "requires": { + "type-fest": "^2.19.0" + }, + "dependencies": { + "type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==" + } + } + }, + "@rollup/pluginutils": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.2.tgz", + "integrity": "sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==", + "dev": true, + "requires": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^2.3.1" + } + }, + "@sideway/address": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz", + "integrity": "sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==", + "dev": true, + "requires": { + "@hapi/hoek": "^9.0.0" + } + }, + "@sideway/formula": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", + "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==", + "dev": true + }, + "@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==", + "dev": true + }, + "@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, + "@socket.io/component-emitter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", + "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" + }, + "@storybook/addon-actions": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-7.6.10.tgz", + "integrity": "sha512-pcKmf0H/caGzKDy8cz1adNSjv+KOBWLJ11RzGExrWm+Ad5ACifwlsQPykJ3TQ/21sTd9IXVrE9uuq4LldEnPbg==", + "dev": true, + "requires": { + "@storybook/core-events": "7.6.10", + "@storybook/global": "^5.0.0", + "@types/uuid": "^9.0.1", + "dequal": "^2.0.2", + "polished": "^4.2.2", + "uuid": "^9.0.0" + }, + "dependencies": { + "uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "dev": true + } + } + }, + "@storybook/addon-backgrounds": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/addon-backgrounds/-/addon-backgrounds-7.6.10.tgz", + "integrity": "sha512-kGzsN1QkfyI8Cz7TErEx9OCB3PMzpCFGLd/iy7FreXwbMbeAQ3/9fYgKUsNOYgOhuTz7S09koZUWjS/WJuZGFA==", + "dev": true, + "requires": { + "@storybook/global": "^5.0.0", + "memoizerific": "^1.11.3", + "ts-dedent": "^2.0.0" + } + }, + "@storybook/addon-controls": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/addon-controls/-/addon-controls-7.6.10.tgz", + "integrity": "sha512-LjwCQRMWq1apLtFwDi6U8MI6ITUr+KhxJucZ60tfc58RgB2v8ayozyDAonFEONsx9YSR1dNIJ2Z/e2rWTBJeYA==", + "dev": true, + "requires": { + "@storybook/blocks": "7.6.10", + "lodash": "^4.17.21", + "ts-dedent": "^2.0.0" + } + }, + "@storybook/addon-docs": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-7.6.10.tgz", + "integrity": "sha512-GtyQ9bMx1AOOtl6ZS9vwK104HFRK+tqzxddRRxhXkpyeKu3olm9aMgXp35atE/3fJSqyyDm2vFtxxH8mzBA20A==", + "dev": true, + "requires": { + "@jest/transform": "^29.3.1", + "@mdx-js/react": "^2.1.5", + "@storybook/blocks": "7.6.10", + "@storybook/client-logger": "7.6.10", + "@storybook/components": "7.6.10", + "@storybook/csf-plugin": "7.6.10", + "@storybook/csf-tools": "7.6.10", + "@storybook/global": "^5.0.0", + "@storybook/mdx2-csf": "^1.0.0", + "@storybook/node-logger": "7.6.10", + "@storybook/postinstall": "7.6.10", + "@storybook/preview-api": "7.6.10", + "@storybook/react-dom-shim": "7.6.10", + "@storybook/theming": "7.6.10", + "@storybook/types": "7.6.10", + "fs-extra": "^11.1.0", + "remark-external-links": "^8.0.0", + "remark-slug": "^6.0.0", + "ts-dedent": "^2.0.0" + }, + "dependencies": { + "fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + } + } + }, + "@storybook/addon-essentials": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/addon-essentials/-/addon-essentials-7.6.10.tgz", + "integrity": "sha512-cjbuCCK/3dtUity0Uqi5LwbkgfxqCCE5x5mXZIk9lTMeDz5vB9q6M5nzncVDy8F8przF3NbDLLgxKlt8wjiICg==", + "dev": true, + "requires": { + "@storybook/addon-actions": "7.6.10", + "@storybook/addon-backgrounds": "7.6.10", + "@storybook/addon-controls": "7.6.10", + "@storybook/addon-docs": "7.6.10", + "@storybook/addon-highlight": "7.6.10", + "@storybook/addon-measure": "7.6.10", + "@storybook/addon-outline": "7.6.10", + "@storybook/addon-toolbars": "7.6.10", + "@storybook/addon-viewport": "7.6.10", + "@storybook/core-common": "7.6.10", + "@storybook/manager-api": "7.6.10", + "@storybook/node-logger": "7.6.10", + "@storybook/preview-api": "7.6.10", + "ts-dedent": "^2.0.0" + } + }, + "@storybook/addon-highlight": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/addon-highlight/-/addon-highlight-7.6.10.tgz", + "integrity": "sha512-dIuS5QmoT1R+gFOcf6CoBa6D9UR5/wHCfPqPRH8dNNcCLtIGSHWQ4v964mS5OCq1Huj7CghmR15lOUk7SaYwUA==", + "dev": true, + "requires": { + "@storybook/global": "^5.0.0" + } + }, + "@storybook/addon-interactions": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/addon-interactions/-/addon-interactions-7.6.10.tgz", + "integrity": "sha512-lEsAdP/PrOZK/KmRbZ/fU4RjEqDP+e/PBlVVVJT2QvHniWK/xxkjCD0axsHU/XuaeQRFhmg0/KR342PC/cIf9A==", + "dev": true, + "requires": { + "@storybook/global": "^5.0.0", + "@storybook/types": "7.6.10", + "jest-mock": "^27.0.6", + "polished": "^4.2.2", + "ts-dedent": "^2.2.0" + } + }, + "@storybook/addon-links": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/addon-links/-/addon-links-7.6.10.tgz", + "integrity": "sha512-s/WkSYHpr2pb9p57j6u/xDBg3TKJhBq55YMl0GB5gXgkRPIeuGbPhGJhm2yTGVFLvXgr/aHHnOxb/R/W8PiRhA==", + "dev": true, + "requires": { + "@storybook/csf": "^0.1.2", + "@storybook/global": "^5.0.0", + "ts-dedent": "^2.0.0" + } + }, + "@storybook/addon-measure": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/addon-measure/-/addon-measure-7.6.10.tgz", + "integrity": "sha512-OVfTI56+kc4hLWfZ/YPV3WKj/aA9e4iKXYxZyPdhfX4Z8TgZdD1wv9Z6e8DKS0H5kuybYrHKHaID5ki6t7qz3w==", + "dev": true, + "requires": { + "@storybook/global": "^5.0.0", + "tiny-invariant": "^1.3.1" + } + }, + "@storybook/addon-outline": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/addon-outline/-/addon-outline-7.6.10.tgz", + "integrity": "sha512-RVJrEoPArhI6zAIMNl1Gz0zrj84BTfEWYYz0yDWOTVgvN411ugsoIk1hw0671MOneXJ2RcQ9MFIeV/v6AVDQYg==", + "dev": true, + "requires": { + "@storybook/global": "^5.0.0", + "ts-dedent": "^2.0.0" + } + }, + "@storybook/addon-toolbars": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/addon-toolbars/-/addon-toolbars-7.6.10.tgz", + "integrity": "sha512-PaXY/oj9yxF7/H0CNdQKcioincyCkfeHpISZriZbZqhyqsjn3vca7RFEmsB88Q+ou6rMeqyA9st+6e2cx/Ct6A==", + "dev": true }, - "@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "@storybook/addon-viewport": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/addon-viewport/-/addon-viewport-7.6.10.tgz", + "integrity": "sha512-+bA6juC/lH4vEhk+w0rXakaG8JgLG4MOYrIudk5vJKQaC6X58LIM9N4kzIS2KSExRhkExXBPrWsnMfCo7uxmKg==", + "dev": true, "requires": { - "eslint-visitor-keys": "^3.3.0" + "memoizerific": "^1.11.3" } }, - "@eslint-community/regexpp": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.4.1.tgz", - "integrity": "sha512-BISJ6ZE4xQsuL/FmsyRaiffpq977bMlsKfGHTQrOGFErfByxIe6iZTxPf/00Zon9b9a7iUykfQwejN3s2ZW/Bw==" + "@storybook/blocks": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/blocks/-/blocks-7.6.10.tgz", + "integrity": "sha512-oSIukGC3yuF8pojABC/HLu5tv2axZvf60TaUs8eDg7+NiiKhzYSPoMQxs5uMrKngl+EJDB92ESgWT9vvsfvIPg==", + "dev": true, + "requires": { + "@storybook/channels": "7.6.10", + "@storybook/client-logger": "7.6.10", + "@storybook/components": "7.6.10", + "@storybook/core-events": "7.6.10", + "@storybook/csf": "^0.1.2", + "@storybook/docs-tools": "7.6.10", + "@storybook/global": "^5.0.0", + "@storybook/manager-api": "7.6.10", + "@storybook/preview-api": "7.6.10", + "@storybook/theming": "7.6.10", + "@storybook/types": "7.6.10", + "@types/lodash": "^4.14.167", + "color-convert": "^2.0.1", + "dequal": "^2.0.2", + "lodash": "^4.17.21", + "markdown-to-jsx": "^7.1.8", + "memoizerific": "^1.11.3", + "polished": "^4.2.2", + "react-colorful": "^5.1.2", + "telejson": "^7.2.0", + "tocbot": "^4.20.1", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2" + }, + "dependencies": { + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + } + } }, - "@eslint/eslintrc": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.1.tgz", - "integrity": "sha512-eFRmABvW2E5Ho6f5fHLqgena46rOj7r7OKHYfLElqcBfGFHHpjBhivyi5+jOEQuSpdc/1phIZJlbC2te+tZNIw==", + "@storybook/builder-manager": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/builder-manager/-/builder-manager-7.6.10.tgz", + "integrity": "sha512-f+YrjZwohGzvfDtH8BHzqM3xW0p4vjjg9u7uzRorqUiNIAAKHpfNrZ/WvwPlPYmrpAHt4xX/nXRJae4rFSygPw==", + "dev": true, + "requires": { + "@fal-works/esbuild-plugin-global-externals": "^2.1.2", + "@storybook/core-common": "7.6.10", + "@storybook/manager": "7.6.10", + "@storybook/node-logger": "7.6.10", + "@types/ejs": "^3.1.1", + "@types/find-cache-dir": "^3.2.1", + "@yarnpkg/esbuild-plugin-pnp": "^3.0.0-rc.10", + "browser-assert": "^1.2.1", + "ejs": "^3.1.8", + "esbuild": "^0.18.0", + "esbuild-plugin-alias": "^0.2.1", + "express": "^4.17.3", + "find-cache-dir": "^3.0.0", + "fs-extra": "^11.1.0", + "process": "^0.11.10", + "util": "^0.12.4" + }, + "dependencies": { + "fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + } + } + }, + "@storybook/builder-vite": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/builder-vite/-/builder-vite-7.6.10.tgz", + "integrity": "sha512-qxe19axiNJVdIKj943e1ucAmADwU42fTGgMSdBzzrvfH3pSOmx2057aIxRzd8YtBRnj327eeqpgCHYIDTunMYQ==", + "dev": true, + "requires": { + "@storybook/channels": "7.6.10", + "@storybook/client-logger": "7.6.10", + "@storybook/core-common": "7.6.10", + "@storybook/csf-plugin": "7.6.10", + "@storybook/node-logger": "7.6.10", + "@storybook/preview": "7.6.10", + "@storybook/preview-api": "7.6.10", + "@storybook/types": "7.6.10", + "@types/find-cache-dir": "^3.2.1", + "browser-assert": "^1.2.1", + "es-module-lexer": "^0.9.3", + "express": "^4.17.3", + "find-cache-dir": "^3.0.0", + "fs-extra": "^11.1.0", + "magic-string": "^0.30.0", + "rollup": "^2.25.0 || ^3.3.0" + }, + "dependencies": { + "es-module-lexer": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", + "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", + "dev": true + }, + "fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + } + } + }, + "@storybook/channels": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-7.6.10.tgz", + "integrity": "sha512-ITCLhFuDBKgxetuKnWwYqMUWlU7zsfH3gEKZltTb+9/2OAWR7ez0iqU7H6bXP1ridm0DCKkt2UMWj2mmr9iQqg==", + "dev": true, + "requires": { + "@storybook/client-logger": "7.6.10", + "@storybook/core-events": "7.6.10", + "@storybook/global": "^5.0.0", + "qs": "^6.10.0", + "telejson": "^7.2.0", + "tiny-invariant": "^1.3.1" + } + }, + "@storybook/cli": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/cli/-/cli-7.6.10.tgz", + "integrity": "sha512-pK1MEseMm73OMO2OVoSz79QWX8ymxgIGM8IeZTCo9gImiVRChMNDFYcv8yPWkjuyesY8c15CoO48aR7pdA1OjQ==", + "dev": true, + "requires": { + "@babel/core": "^7.23.2", + "@babel/preset-env": "^7.23.2", + "@babel/types": "^7.23.0", + "@ndelangen/get-tarball": "^3.0.7", + "@storybook/codemod": "7.6.10", + "@storybook/core-common": "7.6.10", + "@storybook/core-events": "7.6.10", + "@storybook/core-server": "7.6.10", + "@storybook/csf-tools": "7.6.10", + "@storybook/node-logger": "7.6.10", + "@storybook/telemetry": "7.6.10", + "@storybook/types": "7.6.10", + "@types/semver": "^7.3.4", + "@yarnpkg/fslib": "2.10.3", + "@yarnpkg/libzip": "2.3.0", + "chalk": "^4.1.0", + "commander": "^6.2.1", + "cross-spawn": "^7.0.3", + "detect-indent": "^6.1.0", + "envinfo": "^7.7.3", + "execa": "^5.0.0", + "express": "^4.17.3", + "find-up": "^5.0.0", + "fs-extra": "^11.1.0", + "get-npm-tarball-url": "^2.0.3", + "get-port": "^5.1.1", + "giget": "^1.0.0", + "globby": "^11.0.2", + "jscodeshift": "^0.15.1", + "leven": "^3.1.0", + "ora": "^5.4.1", + "prettier": "^2.8.0", + "prompts": "^2.4.0", + "puppeteer-core": "^2.1.1", + "read-pkg-up": "^7.0.1", + "semver": "^7.3.7", + "strip-json-comments": "^3.0.1", + "tempy": "^1.0.1", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "dev": true + }, + "fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "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 + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "@storybook/client-logger": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-7.6.10.tgz", + "integrity": "sha512-U7bbpu21ntgePMz/mKM18qvCSWCUGCUlYru8mgVlXLCKqFqfTeP887+CsPEQf29aoE3cLgDrxqbRJ1wxX9kL9A==", + "dev": true, "requires": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.5.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" + "@storybook/global": "^5.0.0" + } + }, + "@storybook/codemod": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/codemod/-/codemod-7.6.10.tgz", + "integrity": "sha512-pzFR0nocBb94vN9QCJLC3C3dP734ZigqyPmd0ZCDj9Xce2ytfHK3v1lKB6TZWzKAZT8zztauECYxrbo4LVuagw==", + "dev": true, + "requires": { + "@babel/core": "^7.23.2", + "@babel/preset-env": "^7.23.2", + "@babel/types": "^7.23.0", + "@storybook/csf": "^0.1.2", + "@storybook/csf-tools": "7.6.10", + "@storybook/node-logger": "7.6.10", + "@storybook/types": "7.6.10", + "@types/cross-spawn": "^6.0.2", + "cross-spawn": "^7.0.3", + "globby": "^11.0.2", + "jscodeshift": "^0.15.1", + "lodash": "^4.17.21", + "prettier": "^2.8.0", + "recast": "^0.23.1" + } + }, + "@storybook/components": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/components/-/components-7.6.10.tgz", + "integrity": "sha512-H5hF8pxwtbt0LxV24KMMsPlbYG9Oiui3ObvAQkvGu6q62EYxRPeNSrq3GBI5XEbI33OJY9bT24cVaZx18dXqwQ==", + "dev": true, + "requires": { + "@radix-ui/react-select": "^1.2.2", + "@radix-ui/react-toolbar": "^1.0.4", + "@storybook/client-logger": "7.6.10", + "@storybook/csf": "^0.1.2", + "@storybook/global": "^5.0.0", + "@storybook/theming": "7.6.10", + "@storybook/types": "7.6.10", + "memoizerific": "^1.11.3", + "use-resize-observer": "^9.1.0", + "util-deprecate": "^1.0.2" + } + }, + "@storybook/core-client": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/core-client/-/core-client-7.6.10.tgz", + "integrity": "sha512-DjnzSzSNDmZyxyg6TxugzWQwOsW+n/iWVv6sHNEvEd5STr0mjuJjIEELmv58LIr5Lsre5+LEddqHsyuLyt8ubg==", + "dev": true, + "requires": { + "@storybook/client-logger": "7.6.10", + "@storybook/preview-api": "7.6.10" + } + }, + "@storybook/core-common": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/core-common/-/core-common-7.6.10.tgz", + "integrity": "sha512-K3YWqjCKMnpvYsWNjOciwTH6zWbuuZzmOiipziZaVJ+sB1XYmH52Y3WGEm07TZI8AYK9DRgwA13dR/7W0nw72Q==", + "dev": true, + "requires": { + "@storybook/core-events": "7.6.10", + "@storybook/node-logger": "7.6.10", + "@storybook/types": "7.6.10", + "@types/find-cache-dir": "^3.2.1", + "@types/node": "^18.0.0", + "@types/node-fetch": "^2.6.4", + "@types/pretty-hrtime": "^1.0.0", + "chalk": "^4.1.0", + "esbuild": "^0.18.0", + "esbuild-register": "^3.5.0", + "file-system-cache": "2.3.0", + "find-cache-dir": "^3.0.0", + "find-up": "^5.0.0", + "fs-extra": "^11.1.0", + "glob": "^10.0.0", + "handlebars": "^4.7.7", + "lazy-universal-dotenv": "^4.0.0", + "node-fetch": "^2.0.0", + "picomatch": "^2.3.0", + "pkg-dir": "^5.0.0", + "pretty-hrtime": "^1.0.3", + "resolve-from": "^5.0.0", + "ts-dedent": "^2.0.0" + }, + "dependencies": { + "@types/node": { + "version": "18.19.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.9.tgz", + "integrity": "sha512-oZFKlC8l5YtzGQNT4zC2PiSSKzQVZ8bAwwd+EYdPLtyk0nSEq6O16SkK+rkkT2eflDAbormJgEF3QnH3oDrTSw==", + "dev": true, + "requires": { + "undici-types": "~5.26.4" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "requires": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + } + }, + "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 + }, + "minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@storybook/core-events": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-7.6.10.tgz", + "integrity": "sha512-yccDH67KoROrdZbRKwxgTswFMAco5nlCyxszCDASCLygGSV2Q2e+YuywrhchQl3U6joiWi3Ps1qWu56NeNafag==", + "dev": true, + "requires": { + "ts-dedent": "^2.0.0" + } + }, + "@storybook/core-server": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/core-server/-/core-server-7.6.10.tgz", + "integrity": "sha512-2icnqJkn3vwq0eJPP0rNaHd7IOvxYf5q4lSVl2AWTxo/Ae19KhokI6j/2vvS2XQJMGQszwshlIwrZUNsj5p0yw==", + "dev": true, + "requires": { + "@aw-web-design/x-default-browser": "1.4.126", + "@discoveryjs/json-ext": "^0.5.3", + "@storybook/builder-manager": "7.6.10", + "@storybook/channels": "7.6.10", + "@storybook/core-common": "7.6.10", + "@storybook/core-events": "7.6.10", + "@storybook/csf": "^0.1.2", + "@storybook/csf-tools": "7.6.10", + "@storybook/docs-mdx": "^0.1.0", + "@storybook/global": "^5.0.0", + "@storybook/manager": "7.6.10", + "@storybook/node-logger": "7.6.10", + "@storybook/preview-api": "7.6.10", + "@storybook/telemetry": "7.6.10", + "@storybook/types": "7.6.10", + "@types/detect-port": "^1.3.0", + "@types/node": "^18.0.0", + "@types/pretty-hrtime": "^1.0.0", + "@types/semver": "^7.3.4", + "better-opn": "^3.0.2", + "chalk": "^4.1.0", + "cli-table3": "^0.6.1", + "compression": "^1.7.4", + "detect-port": "^1.3.0", + "express": "^4.17.3", + "fs-extra": "^11.1.0", + "globby": "^11.0.2", + "ip": "^2.0.0", + "lodash": "^4.17.21", + "open": "^8.4.0", + "pretty-hrtime": "^1.0.3", + "prompts": "^2.4.0", + "read-pkg-up": "^7.0.1", + "semver": "^7.3.7", + "telejson": "^7.2.0", + "tiny-invariant": "^1.3.1", + "ts-dedent": "^2.0.0", + "util": "^0.12.4", + "util-deprecate": "^1.0.2", + "watchpack": "^2.2.0", + "ws": "^8.2.3" }, "dependencies": { - "globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "@types/node": { + "version": "18.19.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.9.tgz", + "integrity": "sha512-oZFKlC8l5YtzGQNT4zC2PiSSKzQVZ8bAwwd+EYdPLtyk0nSEq6O16SkK+rkkT2eflDAbormJgEF3QnH3oDrTSw==", + "dev": true, "requires": { - "type-fest": "^0.20.2" + "undici-types": "~5.26.4" } }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==" + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "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 + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true } } }, - "@eslint/js": { - "version": "8.36.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.36.0.tgz", - "integrity": "sha512-lxJ9R5ygVm8ZWgYdUweoq5ownDlJ4upvoWmO4eLxBYHdMo+vZ/Rx0EN6MbKWDJOSUGrqJy2Gt+Dyv/VKml0fjg==" - }, - "@floating-ui/core": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.2.5.tgz", - "integrity": "sha512-qrcbyfnRVziRlB6IYwjCopYhO7Vud750JlJyuljruIXcPxr22y8zdckcJGsuOdnQ639uVD1tTXddrcH3t3QYIQ==" - }, - "@floating-ui/dom": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.2.5.tgz", - "integrity": "sha512-+sAUfpQ3Frz+VCbPCqj+cZzvEESy3fjSeT/pDWkYCWOBXYNNKZfuVsHuv8/JO2zze8+Eb/Q7a6hZVgzS81fLbQ==", - "requires": { - "@floating-ui/core": "^1.2.4" - } - }, - "@formbricks/js": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@formbricks/js/-/js-1.2.0.tgz", - "integrity": "sha512-bhQutlEHWnMHm54h6tc2VRM8lj/Rio0tT1L+zNjFv0Hcx4TamZ/967MyhGpY0LnJyqdr8Ck/+DtEWFSAOO5HEw==" - }, - "@hapi/hoek": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", - "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==", - "dev": true - }, - "@hapi/topo": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", - "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "@storybook/csf": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@storybook/csf/-/csf-0.1.2.tgz", + "integrity": "sha512-ePrvE/pS1vsKR9Xr+o+YwdqNgHUyXvg+1Xjx0h9LrVx7Zq4zNe06pd63F5EvzTbCbJsHj7GHr9tkiaqm7U8WRA==", "dev": true, "requires": { - "@hapi/hoek": "^9.0.0" + "type-fest": "^2.19.0" + }, + "dependencies": { + "type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true + } } }, - "@humanwhocodes/config-array": { - "version": "0.11.8", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", - "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", + "@storybook/csf-plugin": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/csf-plugin/-/csf-plugin-7.6.10.tgz", + "integrity": "sha512-Sc+zZg/BnPH2X28tthNaQBnDiFfO0QmfjVoOx0fGYM9SvY3P5ehzWwp5hMRBim6a/twOTzePADtqYL+t6GMqqg==", + "dev": true, "requires": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.5" + "@storybook/csf-tools": "7.6.10", + "unplugin": "^1.3.1" } }, - "@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==" - }, - "@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==" - }, - "@interactjs/actions": { - "version": "1.10.17", - "resolved": "https://registry.npmjs.org/@interactjs/actions/-/actions-1.10.17.tgz", - "integrity": "sha512-wyB1ZqpaZy5gmz6VDqK9KWh98xKnFgL7VyLvxHODFi9V0IYX4HJAAOBlhtfze0D1R1f1cY+gqPDK+dLaHMlE+w==", + "@storybook/csf-tools": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/csf-tools/-/csf-tools-7.6.10.tgz", + "integrity": "sha512-TnDNAwIALcN6SA4l00Cb67G02XMOrYU38bIpFJk5VMDX2dvgPjUtJNBuLmEbybGcOt7nPyyFIHzKcY5FCVGoWA==", + "dev": true, "requires": { - "@interactjs/interact": "1.10.17" + "@babel/generator": "^7.23.0", + "@babel/parser": "^7.23.0", + "@babel/traverse": "^7.23.2", + "@babel/types": "^7.23.0", + "@storybook/csf": "^0.1.2", + "@storybook/types": "7.6.10", + "fs-extra": "^11.1.0", + "recast": "^0.23.1", + "ts-dedent": "^2.0.0" + }, + "dependencies": { + "fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + } } }, - "@interactjs/auto-scroll": { - "version": "1.10.17", - "resolved": "https://registry.npmjs.org/@interactjs/auto-scroll/-/auto-scroll-1.10.17.tgz", - "integrity": "sha512-IQcW7N3xOaoL8RnAGOGMk0Y2gue7L4S3BT6Id4VBBu8so163DtLiZVW6jXu9rKVntzbluaAeqNZlfAVyu3kIWg==", - "requires": { - "@interactjs/interact": "1.10.17" - } + "@storybook/docs-mdx": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@storybook/docs-mdx/-/docs-mdx-0.1.0.tgz", + "integrity": "sha512-JDaBR9lwVY4eSH5W8EGHrhODjygPd6QImRbwjAuJNEnY0Vw4ie3bPkeGfnacB3OBW6u/agqPv2aRlR46JcAQLg==", + "dev": true }, - "@interactjs/auto-start": { - "version": "1.10.17", - "resolved": "https://registry.npmjs.org/@interactjs/auto-start/-/auto-start-1.10.17.tgz", - "integrity": "sha512-qYVxhAbYnwxjD/NLEegUoAST7WASJ4VmWNjsyWRx/js5Op+I4E2zteARIeZGgrutcGIXMCcQzhCMgE3PjOpbpw==", + "@storybook/docs-tools": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/docs-tools/-/docs-tools-7.6.10.tgz", + "integrity": "sha512-UgbikducoXzqQHf2TozO0f2rshaeBNnShVbL5Ai4oW7pDymBmrfzdjGbF/milO7yxNKcoIByeoNmu384eBamgQ==", + "dev": true, "requires": { - "@interactjs/interact": "1.10.17" + "@storybook/core-common": "7.6.10", + "@storybook/preview-api": "7.6.10", + "@storybook/types": "7.6.10", + "@types/doctrine": "^0.0.3", + "assert": "^2.1.0", + "doctrine": "^3.0.0", + "lodash": "^4.17.21" } }, - "@interactjs/core": { - "version": "1.10.17", - "resolved": "https://registry.npmjs.org/@interactjs/core/-/core-1.10.17.tgz", - "integrity": "sha512-rL9w+83HDRuXub8Ezqs+97CYLl/ne7bLT/sAeduUWaxYhsW9iOqBoob9JnkkCZOaOsYizWI1EWy0+fNc5ibtLQ==", - "requires": {} - }, - "@interactjs/dev-tools": { - "version": "1.10.17", - "resolved": "https://registry.npmjs.org/@interactjs/dev-tools/-/dev-tools-1.10.17.tgz", - "integrity": "sha512-Oi9nEw3FfSwkNmW+V0WwdHqvzEkVHc24mH1v5EjRn60sqgrGLK9nTQ+NSuqcnUY8GxC3TkyuxnsOodxiadIRmA==", - "requires": { - "@interactjs/interact": "1.10.17" - } + "@storybook/global": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@storybook/global/-/global-5.0.0.tgz", + "integrity": "sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ==", + "dev": true }, - "@interactjs/inertia": { - "version": "1.10.17", - "resolved": "https://registry.npmjs.org/@interactjs/inertia/-/inertia-1.10.17.tgz", - "integrity": "sha512-41vbYUjZIDCKt2/yhmjPrEW5+0uoL/hldFsll9pkvnLhmm12Xk0VXOlmR2zXKAmsTK3fJlKMyBYUX92qHLkyVQ==", + "@storybook/instrumenter": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/instrumenter/-/instrumenter-7.6.10.tgz", + "integrity": "sha512-9FYXW1CKXnZ7yYmy2A6U0seqJMe1F7g55J28Vslk3ZLoGATFJ2BR0eoQS+cgfBly6djehjaVeuV3IcUYGnQ/6Q==", + "dev": true, "requires": { - "@interactjs/interact": "1.10.17", - "@interactjs/offset": "1.10.17" + "@storybook/channels": "7.6.10", + "@storybook/client-logger": "7.6.10", + "@storybook/core-events": "7.6.10", + "@storybook/global": "^5.0.0", + "@storybook/preview-api": "7.6.10", + "@vitest/utils": "^0.34.6", + "util": "^0.12.4" } }, - "@interactjs/interact": { - "version": "1.10.17", - "resolved": "https://registry.npmjs.org/@interactjs/interact/-/interact-1.10.17.tgz", - "integrity": "sha512-NyKsf8EFudvdahBjPz1Gt5QnynVwa/2LUfBc2/w8QOnOBiyzUm0HLloJSaB8a50QbQkSWN243/Lgpd8GTMQvuQ==", - "requires": { - "@interactjs/core": "1.10.17", - "@interactjs/types": "1.10.17", - "@interactjs/utils": "1.10.17" - } + "@storybook/manager": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/manager/-/manager-7.6.10.tgz", + "integrity": "sha512-Co3sLCbNYY6O4iH2ggmRDLCPWLj03JE5s/DOG8OVoXc6vBwTc/Qgiyrsxxp6BHQnPpM0mxL6aKAxE3UjsW/Nog==", + "dev": true }, - "@interactjs/interactjs": { - "version": "1.10.17", - "resolved": "https://registry.npmjs.org/@interactjs/interactjs/-/interactjs-1.10.17.tgz", - "integrity": "sha512-hHmiukARbZhiM12zNKx0yQlFVl4C+NMeYNAYh6Mf9U3ZziQ47C+JEW8Gr7Zr/MxfNZyPu5nLKCpVQjh/JvBO9g==", - "requires": { - "@interactjs/actions": "1.10.17", - "@interactjs/auto-scroll": "1.10.17", - "@interactjs/auto-start": "1.10.17", - "@interactjs/core": "1.10.17", - "@interactjs/dev-tools": "1.10.17", - "@interactjs/inertia": "1.10.17", - "@interactjs/interact": "1.10.17", - "@interactjs/modifiers": "1.10.17", - "@interactjs/offset": "1.10.17", - "@interactjs/pointer-events": "1.10.17", - "@interactjs/reflow": "1.10.17", - "@interactjs/utils": "1.10.17" + "@storybook/manager-api": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/manager-api/-/manager-api-7.6.10.tgz", + "integrity": "sha512-8eGVpRlpunuFScDtc7nxpPJf/4kJBAAZlNdlhmX09j8M3voX6GpcxabBamSEX5pXZqhwxQCshD4IbqBmjvadlw==", + "dev": true, + "requires": { + "@storybook/channels": "7.6.10", + "@storybook/client-logger": "7.6.10", + "@storybook/core-events": "7.6.10", + "@storybook/csf": "^0.1.2", + "@storybook/global": "^5.0.0", + "@storybook/router": "7.6.10", + "@storybook/theming": "7.6.10", + "@storybook/types": "7.6.10", + "dequal": "^2.0.2", + "lodash": "^4.17.21", + "memoizerific": "^1.11.3", + "store2": "^2.14.2", + "telejson": "^7.2.0", + "ts-dedent": "^2.0.0" } }, - "@interactjs/modifiers": { - "version": "1.10.17", - "resolved": "https://registry.npmjs.org/@interactjs/modifiers/-/modifiers-1.10.17.tgz", - "integrity": "sha512-Dxw8kv9VBIxnhNvQncR6CKAGMzKXczLvuAUIdSPFYtyerX/XiDulJUqhR+jVKNp/WjF1DvdBxWo0kGGLbM84LQ==", - "requires": { - "@interactjs/interact": "1.10.17", - "@interactjs/snappers": "1.10.17" - } + "@storybook/mdx2-csf": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@storybook/mdx2-csf/-/mdx2-csf-1.1.0.tgz", + "integrity": "sha512-TXJJd5RAKakWx4BtpwvSNdgTDkKM6RkXU8GK34S/LhidQ5Pjz3wcnqb0TxEkfhK/ztbP8nKHqXFwLfa2CYkvQw==", + "dev": true }, - "@interactjs/offset": { - "version": "1.10.17", - "resolved": "https://registry.npmjs.org/@interactjs/offset/-/offset-1.10.17.tgz", - "integrity": "sha512-wWBnIQWgLrmJNTBbd/FdxHxAJjiXl/5ND8Jbw2DuP9gIGDxhFSdEt62Fgqimn9ICb8v8ycvSLObEmcvJF/8hQQ==", - "requires": { - "@interactjs/interact": "1.10.17" - } + "@storybook/node-logger": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-7.6.10.tgz", + "integrity": "sha512-ZBuqrv4bjJzKXyfRGFkVIi+z6ekn6rOPoQao4KmsfLNQAUUsEdR8Baw/zMnnU417zw5dSEaZdpuwx75SCQAeOA==", + "dev": true }, - "@interactjs/pointer-events": { - "version": "1.10.17", - "resolved": "https://registry.npmjs.org/@interactjs/pointer-events/-/pointer-events-1.10.17.tgz", - "integrity": "sha512-VsfluouEKb8QRGyH6jQATCW+QdAd/3dkENS7rj2m+EcVUhz2Ob5mpMRopjALi4pwltMowqTfuJ4LtwMSX2G29A==", - "requires": { - "@interactjs/interact": "1.10.17" - } + "@storybook/postinstall": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/postinstall/-/postinstall-7.6.10.tgz", + "integrity": "sha512-SMdXtednPCy3+SRJ7oN1OPN1oVFhj3ih+ChOEX8/kZ5J3nfmV3wLPtsZvFGUCf0KWQEP1xL+1Urv48mzMKcV/w==", + "dev": true }, - "@interactjs/reflow": { - "version": "1.10.17", - "resolved": "https://registry.npmjs.org/@interactjs/reflow/-/reflow-1.10.17.tgz", - "integrity": "sha512-ncpWP5k93FRQptEhjzPZsbuRRajd4rkW17lDavCrEjrDi/LHnYekWGqZTaFzfJ80n1x8xUm9ujDjxCTylNqEIA==", - "requires": { - "@interactjs/interact": "1.10.17" - } + "@storybook/preview": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/preview/-/preview-7.6.10.tgz", + "integrity": "sha512-F07BzVXTD3byq+KTWtvsw3pUu3fQbyiBNLFr2CnfU4XSdLKja5lDt8VqDQq70TayVQOf5qfUTzRd4M6pQkjw1w==", + "dev": true }, - "@interactjs/snappers": { - "version": "1.10.17", - "resolved": "https://registry.npmjs.org/@interactjs/snappers/-/snappers-1.10.17.tgz", - "integrity": "sha512-m753DGsNOts797e3zDT6wqELoc+BlpIC1w+TyMyISRxU6n1RlS8Q6LHBGgwAgV79LHLaahv/a5haFF9H1VG0FQ==", + "@storybook/preview-api": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-7.6.10.tgz", + "integrity": "sha512-5A3etoIwZCx05yuv3KSTv1wynN4SR4rrzaIs/CTBp3BC4q1RBL+Or/tClk0IJPXQMlx/4Y134GtNIBbkiDofpw==", + "dev": true, "requires": { - "@interactjs/interact": "1.10.17" + "@storybook/channels": "7.6.10", + "@storybook/client-logger": "7.6.10", + "@storybook/core-events": "7.6.10", + "@storybook/csf": "^0.1.2", + "@storybook/global": "^5.0.0", + "@storybook/types": "7.6.10", + "@types/qs": "^6.9.5", + "dequal": "^2.0.2", + "lodash": "^4.17.21", + "memoizerific": "^1.11.3", + "qs": "^6.10.0", + "synchronous-promise": "^2.0.15", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2" } }, - "@interactjs/types": { - "version": "1.10.17", - "resolved": "https://registry.npmjs.org/@interactjs/types/-/types-1.10.17.tgz", - "integrity": "sha512-X2JpoM7xUw0p9Me0tMaI0HNfcF/Hd07ZZlzpnpEMpGerUZOLoyeThrV9P+CrBHxZrluWJrigJbcdqXliFd0YMA==" - }, - "@interactjs/utils": { - "version": "1.10.17", - "resolved": "https://registry.npmjs.org/@interactjs/utils/-/utils-1.10.17.tgz", - "integrity": "sha512-sZAW08CkqgvqRjUIaLRjScjObcCzN9D75yekLA21EClYAZIhi4A+GEt2z/WqOCOksTaEPLYmQyhkpXcboc0LhQ==" + "@storybook/react-dom-shim": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-7.6.10.tgz", + "integrity": "sha512-M+N/h6ximacaFdIDjMN2waNoWwApeVYTpFeoDppiFTvdBTXChyIuiPgYX9QSg7gDz92OaA52myGOot4wGvXVzg==", + "dev": true, + "requires": {} }, - "@jest/schemas": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.3.tgz", - "integrity": "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==", + "@storybook/router": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/router/-/router-7.6.10.tgz", + "integrity": "sha512-G/H4Jn2+y8PDe8Zbq4DVxF/TPn0/goSItdILts39JENucHiuGBCjKjSWGBe1rkwKi1tUbB3yhxJVrLagxFEPpQ==", "dev": true, "requires": { - "@sinclair/typebox": "^0.25.16" + "@storybook/client-logger": "7.6.10", + "memoizerific": "^1.11.3", + "qs": "^6.10.0" } }, - "@jest/types": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.5.0.tgz", - "integrity": "sha512-qbu7kN6czmVRc3xWFQcAN03RAUamgppVUdXrvl1Wr3jlNF93o9mJbGcDWrwGB6ht44u7efB1qCFgVQmca24Uog==", + "@storybook/telemetry": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/telemetry/-/telemetry-7.6.10.tgz", + "integrity": "sha512-p3mOSUtIyy2tF1z6pQXxNh1JzYFcAm97nUgkwLzF07GfEdVAPM+ftRSLFbD93zVvLEkmLTlsTiiKaDvOY/lQWg==", "dev": true, "requires": { - "@jest/schemas": "^29.4.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" + "@storybook/client-logger": "7.6.10", + "@storybook/core-common": "7.6.10", + "@storybook/csf-tools": "7.6.10", + "chalk": "^4.1.0", + "detect-package-manager": "^2.0.1", + "fetch-retry": "^5.0.2", + "fs-extra": "^11.1.0", + "read-pkg-up": "^7.0.1" }, "dependencies": { "ansi-styles": { @@ -12973,338 +25195,191 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "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 - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", "dev": true, "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "@jridgewell/gen-mapping": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", - "requires": { - "@jridgewell/set-array": "^1.0.0", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==" - }, - "@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==" - }, - "@jridgewell/source-map": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", - "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", - "requires": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "dependencies": { - "@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "requires": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" } - } - } - }, - "@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" - }, - "@jridgewell/trace-mapping": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", - "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", - "requires": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" - } - }, - "@koa/router": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/@koa/router/-/router-9.4.0.tgz", - "integrity": "sha512-dOOXgzqaDoHu5qqMEPLKEgLz5CeIA7q8+1W62mCvFVCOqeC71UoTGJ4u1xUSOpIl2J1x2pqrNULkFteUeZW3/A==", - "dev": true, - "requires": { - "debug": "^4.1.1", - "http-errors": "^1.7.3", - "koa-compose": "^4.1.0", - "methods": "^1.1.2", - "path-to-regexp": "^6.1.0" - } - }, - "@linaria/core": { - "version": "4.2.9", - "resolved": "https://registry.npmjs.org/@linaria/core/-/core-4.2.9.tgz", - "integrity": "sha512-ELcu37VNVOT/PU0L6WDIN+aLzNFyJrqoBYT0CucGOCAmODbojUMCv8oJYRbWzA3N34w1t199dN4UFdfRWFG2rg==", - "requires": { - "@linaria/logger": "^4.0.0", - "@linaria/tags": "^4.3.4", - "@linaria/utils": "^4.3.3" - } - }, - "@linaria/logger": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@linaria/logger/-/logger-4.0.0.tgz", - "integrity": "sha512-YnBq0JlDWMEkTOK+tMo5yEVR0f5V//6qMLToGcLhTyM9g9i+IDFn51Z+5q2hLk7RdG4NBPgbcCXYi2w4RKsPeg==", - "requires": { - "debug": "^4.1.1", - "picocolors": "^1.0.0" - } - }, - "@linaria/tags": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/@linaria/tags/-/tags-4.3.5.tgz", - "integrity": "sha512-PgaIi8Vv89YOjc6rpKL/uPg2w4k0rAwAYxcqeXqzKqsEAste5rgB8xp1/KUOG0oAOkPd3MRL6Duj+m0ZwJ3g+g==", - "requires": { - "@babel/generator": "^7.20.4", - "@linaria/logger": "^4.0.0", - "@linaria/utils": "^4.3.4" - } - }, - "@linaria/utils": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/@linaria/utils/-/utils-4.3.4.tgz", - "integrity": "sha512-vt6WJG54n+KANaqxOfzIIU7aSfFHEWFbnGLsgxL7nASHqO0zezrNA2y2Rrp80zSeTW+wSpbmDM4uJyC9UW1qoA==", - "requires": { - "@babel/core": "^7.20.2", - "@babel/plugin-proposal-export-namespace-from": "^7.18.9", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-transform-modules-commonjs": "^7.19.6", - "@babel/traverse": "^7.20.1", - "@babel/types": "^7.20.2", - "@linaria/logger": "^4.0.0", - "babel-merge": "^3.0.0" - } - }, - "@loomhq/loom-embed": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@loomhq/loom-embed/-/loom-embed-1.5.0.tgz", - "integrity": "sha512-1Rilv+Ta39Rk2mEb8wzfLSpPhl6ax7kfLNnfYTAGK4mCJIxwQ1o/BY46QRbIpQT/SdfsFCvvNWa57hlEEaduGA==" - }, - "@nangohq/frontend": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@nangohq/frontend/-/frontend-0.9.0.tgz", - "integrity": "sha512-LLM74Bs1LQ8LalN2zokC/6MEeNMmpGyFAsVTmg5xpeYWXsHG7B1qh4LAUDKWrRM9z9J8r5Y/+hEUv3WJtum1Rw==" - }, - "@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==" - }, - "@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - } - }, - "@octokit/auth-token": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz", - "integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==", - "requires": { - "@octokit/types": "^6.0.3" - } - }, - "@octokit/core": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz", - "integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==", - "requires": { - "@octokit/auth-token": "^2.4.4", - "@octokit/graphql": "^4.5.8", - "@octokit/request": "^5.6.3", - "@octokit/request-error": "^2.0.5", - "@octokit/types": "^6.0.3", - "before-after-hook": "^2.2.0", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/endpoint": { - "version": "6.0.12", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", - "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", - "requires": { - "@octokit/types": "^6.0.3", - "is-plain-object": "^5.0.0", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/graphql": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz", - "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==", - "requires": { - "@octokit/request": "^5.6.0", - "@octokit/types": "^6.0.3", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/openapi-types": { - "version": "12.11.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", - "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==" - }, - "@octokit/request": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz", - "integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==", - "requires": { - "@octokit/endpoint": "^6.0.1", - "@octokit/request-error": "^2.1.0", - "@octokit/types": "^6.16.1", - "is-plain-object": "^5.0.0", - "node-fetch": "^2.6.7", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/request-error": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", - "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", - "requires": { - "@octokit/types": "^6.0.3", - "deprecation": "^2.0.0", - "once": "^1.4.0" + }, + "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 + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } }, - "@octokit/types": { - "version": "6.41.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", - "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", + "@storybook/test": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/test/-/test-7.6.10.tgz", + "integrity": "sha512-dn/T+HcWOBlVh3c74BHurp++BaqBoQgNbSIaXlYDpJoZ+DzNIoEQVsWFYm5gCbtKK27iFd4n52RiQI3f6Vblqw==", + "dev": true, "requires": { - "@octokit/openapi-types": "^12.11.0" + "@storybook/client-logger": "7.6.10", + "@storybook/core-events": "7.6.10", + "@storybook/instrumenter": "7.6.10", + "@storybook/preview-api": "7.6.10", + "@testing-library/dom": "^9.3.1", + "@testing-library/jest-dom": "^6.1.3", + "@testing-library/user-event": "14.3.0", + "@types/chai": "^4", + "@vitest/expect": "^0.34.2", + "@vitest/spy": "^0.34.1", + "chai": "^4.3.7", + "util": "^0.12.4" + }, + "dependencies": { + "@testing-library/jest-dom": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.3.0.tgz", + "integrity": "sha512-hJVIrkFizEQxoWsGBlycTcQhrpoCH4DhXfrnHFFXgkx3Xdm15zycsq5Ep+vpw4W8S0NJa8cxDHcuJib+1tEbhg==", + "dev": true, + "requires": { + "@adobe/css-tools": "^4.3.2", + "@babel/runtime": "^7.9.2", + "aria-query": "^5.0.0", + "chalk": "^3.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.6.3", + "lodash": "^4.17.15", + "redent": "^3.0.0" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "dom-accessibility-api": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", + "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", + "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 + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } }, - "@popperjs/core": { - "version": "npm:@sxzz/popperjs-es@2.11.7", - "resolved": "https://registry.npmjs.org/@sxzz/popperjs-es/-/popperjs-es-2.11.7.tgz", - "integrity": "sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ==" - }, - "@remirror/core-constants": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@remirror/core-constants/-/core-constants-2.0.1.tgz", - "integrity": "sha512-ZR4aihtnnT9lMbhh5DEbsriJRlukRXmLZe7HmM+6ufJNNUDoazc75UX26xbgQlNUqgAqMcUdGFAnPc1JwgAdLQ==", + "@storybook/theming": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-7.6.10.tgz", + "integrity": "sha512-f5tuy7yV3TOP3fIboSqpgLHy0wKayAw/M8HxX0jVET4Z4fWlFK0BiHJabQ+XEdAfQM97XhPFHB2IPbwsqhCEcQ==", + "dev": true, "requires": { - "@babel/runtime": "^7.21.0" + "@emotion/use-insertion-effect-with-fallbacks": "^1.0.0", + "@storybook/client-logger": "7.6.10", + "@storybook/global": "^5.0.0", + "memoizerific": "^1.11.3" } }, - "@remirror/core-helpers": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@remirror/core-helpers/-/core-helpers-2.0.3.tgz", - "integrity": "sha512-LqIPF4stGG69l9qu/FFicv9d9B+YaItzgDMC5A0CEvDQfKkGD3BfabLmfpnuWbsc06oKGdTduilgWcALLZoYLg==", + "@storybook/types": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/types/-/types-7.6.10.tgz", + "integrity": "sha512-hcS2HloJblaMpCAj2axgGV+53kgSRYPT0a1PG1IHsZaYQILfHSMmBqM8XzXXYTsgf9250kz3dqFX1l0n3EqMlQ==", + "dev": true, "requires": { - "@babel/runtime": "^7.21.0", - "@linaria/core": "4.2.9", - "@remirror/core-constants": "^2.0.1", - "@remirror/types": "^1.0.1", - "@types/object.omit": "^3.0.0", - "@types/object.pick": "^1.3.2", - "@types/throttle-debounce": "^2.1.0", - "case-anything": "^2.1.10", - "dash-get": "^1.0.2", - "deepmerge": "^4.3.1", - "fast-deep-equal": "^3.1.3", - "make-error": "^1.3.6", - "object.omit": "^3.0.0", - "object.pick": "^1.3.0", - "throttle-debounce": "^3.0.1" + "@storybook/channels": "7.6.10", + "@types/babel__core": "^7.0.0", + "@types/express": "^4.7.0", + "file-system-cache": "2.3.0" } }, - "@remirror/types": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@remirror/types/-/types-1.0.1.tgz", - "integrity": "sha512-VlZQxwGnt1jtQ18D6JqdIF+uFZo525WEqrfp9BOc3COPpK4+AWCgdnAWL+ho6imWcoINlGjR/+3b6y5C1vBVEA==", + "@storybook/vue3": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/vue3/-/vue3-7.6.10.tgz", + "integrity": "sha512-FeZ9zjuudQgCdKPs2K8sU6TgEyrMjKrCN3e8+XXX5CAMSwLDV8IfexaaMF0ehYW6Wp0dgCIm0cVNBV3u8vtRRw==", + "dev": true, "requires": { - "type-fest": "^2.19.0" + "@storybook/core-client": "7.6.10", + "@storybook/docs-tools": "7.6.10", + "@storybook/global": "^5.0.0", + "@storybook/preview-api": "7.6.10", + "@storybook/types": "7.6.10", + "@vue/compiler-core": "^3.0.0", + "lodash": "^4.17.21", + "ts-dedent": "^2.0.0", + "type-fest": "~2.19", + "vue-component-type-helpers": "latest" }, "dependencies": { "type-fest": { "version": "2.19.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==" + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true } } }, - "@rollup/pluginutils": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.2.tgz", - "integrity": "sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==", - "dev": true, - "requires": { - "@types/estree": "^1.0.0", - "estree-walker": "^2.0.2", - "picomatch": "^2.3.1" - } - }, - "@sideway/address": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz", - "integrity": "sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==", + "@storybook/vue3-vite": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/@storybook/vue3-vite/-/vue3-vite-7.6.10.tgz", + "integrity": "sha512-5f0Rh4PTVEeAI86ybihfN+rHGXXLNiRsoGKinpJSb7hkfsq/L7u3sVCXJwH/qsG+rUJlZyHs3kfa4/Kgyyi3Mg==", "dev": true, "requires": { - "@hapi/hoek": "^9.0.0" + "@storybook/builder-vite": "7.6.10", + "@storybook/core-server": "7.6.10", + "@storybook/vue3": "7.6.10", + "@vitejs/plugin-vue": "^4.0.0", + "magic-string": "^0.30.0", + "vue-docgen-api": "^4.40.0" } }, - "@sideway/formula": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", - "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==", - "dev": true - }, - "@sideway/pinpoint": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", - "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==", - "dev": true - }, - "@sinclair/typebox": { - "version": "0.25.24", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.24.tgz", - "integrity": "sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==", - "dev": true - }, - "@socket.io/component-emitter": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", - "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" - }, "@tailwindcss/line-clamp": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/@tailwindcss/line-clamp/-/line-clamp-0.4.2.tgz", @@ -13312,6 +25387,80 @@ "dev": true, "requires": {} }, + "@testing-library/dom": { + "version": "9.3.4", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.3.4.tgz", + "integrity": "sha512-FlS4ZWlp97iiNWig0Muq8p+3rVDjRiYE+YKGbAqXOu9nwJFFOdL00kFpz42M+4huzYi86vAK1sOOfyOG45muIQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.1.3", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "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 + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@testing-library/user-event": { + "version": "14.3.0", + "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.3.0.tgz", + "integrity": "sha512-P02xtBBa8yMaLhK8CzJCIns8rqwnF6FxhR9zs810flHOBXUYCFjLd8Io1rQrAkQRWEmW2PGdZIEdMxf/KLsqFA==", + "dev": true, + "requires": {} + }, "@tiptap/core": { "version": "2.1.12", "resolved": "https://registry.npmjs.org/@tiptap/core/-/core-2.1.12.tgz", @@ -13507,19 +25656,124 @@ "@tiptap/extension-text": "^2.1.12" } }, - "@tiptap/vue-3": { - "version": "2.1.12", - "resolved": "https://registry.npmjs.org/@tiptap/vue-3/-/vue-3-2.1.12.tgz", - "integrity": "sha512-yAcfmWw/9jtIUbhb0uGQVI9NoPYgHRasX2sAGWnm9Al+0aJktgmQ3mLCifXfXfjyEbeMF0p2L6Ul8tO7eho7aQ==", + "@tiptap/vue-3": { + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/@tiptap/vue-3/-/vue-3-2.1.12.tgz", + "integrity": "sha512-yAcfmWw/9jtIUbhb0uGQVI9NoPYgHRasX2sAGWnm9Al+0aJktgmQ3mLCifXfXfjyEbeMF0p2L6Ul8tO7eho7aQ==", + "requires": { + "@tiptap/extension-bubble-menu": "^2.1.12", + "@tiptap/extension-floating-menu": "^2.1.12" + } + }, + "@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "dev": true + }, + "@types/aria-query": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", + "dev": true + }, + "@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "requires": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@types/babel__traverse": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.5.tgz", + "integrity": "sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==", + "dev": true, + "requires": { + "@babel/types": "^7.20.7" + } + }, + "@types/body-parser": { + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "dev": true, + "requires": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "@types/chai": { + "version": "4.3.11", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.11.tgz", + "integrity": "sha512-qQR1dr2rGIHYlJulmr8Ioq3De0Le9E4MJ5AiaeAETJJpndT1uUNHsGFK3L/UIu+rbkQSdj8J/w2bCsBZc/Y5fQ==", + "dev": true + }, + "@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/cross-spawn": { + "version": "6.0.6", + "resolved": "https://registry.npmjs.org/@types/cross-spawn/-/cross-spawn-6.0.6.tgz", + "integrity": "sha512-fXRhhUkG4H3TQk5dBhQ7m/JDdSNHKwR2BBia62lhwEIq9xGiQKLxd6LymNhn47SjXhsUEPmxi+PKw2OkW4LLjA==", + "dev": true, "requires": { - "@tiptap/extension-bubble-menu": "^2.1.12", - "@tiptap/extension-floating-menu": "^2.1.12" + "@types/node": "*" } }, - "@trysound/sax": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", - "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "@types/detect-port": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/detect-port/-/detect-port-1.3.5.tgz", + "integrity": "sha512-Rf3/lB9WkDfIL9eEKaSYKc+1L/rNVYBjThk22JTqQw0YozXarX8YljFAz+HCoC6h4B4KwCMsBPZHaFezwT4BNA==", + "dev": true + }, + "@types/doctrine": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@types/doctrine/-/doctrine-0.0.3.tgz", + "integrity": "sha512-w5jZ0ee+HaPOaX25X2/2oGR/7rgAQSYII7X7pp0m9KgBfMP7uKfMfTvcpl5Dj+eDBbpxKGiqE+flqDr6XTd2RA==", + "dev": true + }, + "@types/ejs": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@types/ejs/-/ejs-3.1.5.tgz", + "integrity": "sha512-nv+GSx77ZtXiJzwKdsASqi+YQ5Z7vwHsTP0JY2SiQgjGckkBRKZnk8nIM+7oUZ1VCtuTz0+By4qVR7fqzp/Dfg==", + "dev": true + }, + "@types/emscripten": { + "version": "1.39.10", + "resolved": "https://registry.npmjs.org/@types/emscripten/-/emscripten-1.39.10.tgz", + "integrity": "sha512-TB/6hBkYQJxsZHSqyeuO1Jt0AB/bW6G7rHt9g7lML7SOF6lbgcHvw/Lr+69iqN0qxgXLhWKScAon73JNnptuDw==", "dev": true }, "@types/eslint": { @@ -13547,6 +25801,51 @@ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz", "integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==" }, + "@types/express": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "dev": true, + "requires": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "@types/express-serve-static-core": { + "version": "4.17.41", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.41.tgz", + "integrity": "sha512-OaJ7XLaelTgrvlZD8/aa0vvvxZdUmlCn6MtWeB7TkiKW70BQLc9XEPpDLPdbo52ZhXUCrznlWdCHWxJWtdyajA==", + "dev": true, + "requires": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "@types/find-cache-dir": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@types/find-cache-dir/-/find-cache-dir-3.2.1.tgz", + "integrity": "sha512-frsJrz2t/CeGifcu/6uRo4b+SzAwT4NYCVPu1GN8IB9XTzrpPkGuV0tmh9mN+/L0PklAlsC3u5Fxt0ju00LXIw==", + "dev": true + }, + "@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/http-errors": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", + "dev": true + }, "@types/istanbul-lib-coverage": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", @@ -13594,11 +25893,58 @@ "@types/lodash": "*" } }, + "@types/mdx": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.10.tgz", + "integrity": "sha512-Rllzc5KHk0Al5/WANwgSPl1/CwjqCy+AZrGd78zuK+jO9aDM6ffblZ+zIjgPNAaEBmlO0RYDvLNh7wD0zKVgEg==", + "dev": true + }, + "@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true + }, + "@types/mime-types": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@types/mime-types/-/mime-types-2.1.4.tgz", + "integrity": "sha512-lfU4b34HOri+kAY5UheuFMWPDOI+OPceBSHZKp69gEyTL/mmJ4cnU6Y/rlme3UL3GyOn6Y42hyIEw0/q8sWx5w==", + "dev": true + }, "@types/node": { "version": "14.18.41", "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.41.tgz", "integrity": "sha512-2cfHr8AsUjKx6u4Q+d2eqK51z8+HueoumCQGCKVt95y/yGG4uajOuCANSnE20mbLw94h3tMcddIJ8nYkTu2mFw==" }, + "@types/node-fetch": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.11.tgz", + "integrity": "sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==", + "dev": true, + "requires": { + "@types/node": "*", + "form-data": "^4.0.0" + }, + "dependencies": { + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + } + } + }, + "@types/normalize-package-data": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", + "dev": true + }, "@types/object.omit": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/object.omit/-/object.omit-3.0.0.tgz", @@ -13609,12 +25955,80 @@ "resolved": "https://registry.npmjs.org/@types/object.pick/-/object.pick-1.3.2.tgz", "integrity": "sha512-sn7L+qQ6RLPdXRoiaE7bZ/Ek+o4uICma/lBFPyJEKDTPTBP1W8u0c4baj3EiS4DiqLs+Hk+KUGvMVJtAw3ePJg==" }, + "@types/pluralize": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/@types/pluralize/-/pluralize-0.0.33.tgz", + "integrity": "sha512-JOqsl+ZoCpP4e8TDke9W79FDcSgPAR0l6pixx2JHkhnRjvShyYiAYw2LVsnA7K08Y6DeOnaU6ujmENO4os/cYg==", + "dev": true + }, + "@types/pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha512-nj39q0wAIdhwn7DGUyT9irmsKK1tV0bd5WFEhgpqNTMFZ8cE+jieuTphCW0tfdm47S2zVT5mr09B28b1chmQMA==", + "dev": true + }, + "@types/prop-types": { + "version": "15.7.11", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz", + "integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==", + "dev": true + }, + "@types/qs": { + "version": "6.9.11", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.11.tgz", + "integrity": "sha512-oGk0gmhnEJK4Yyk+oI7EfXsLayXatCWPHary1MtcmbAifkobT9cM9yutG/hZKIseOU0MqbIwQ/u2nn/Gb+ltuQ==", + "dev": true + }, + "@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true + }, + "@types/react": { + "version": "18.2.48", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.48.tgz", + "integrity": "sha512-qboRCl6Ie70DQQG9hhNREz81jqC1cs9EVNcjQ1AU+jH6NFfSAhVVbrrY/+nSF+Bsk4AOwm9Qa61InvMCyV+H3w==", + "dev": true, + "requires": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "@types/scheduler": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz", + "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==", + "dev": true + }, "@types/semver": { "version": "7.5.0", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", "dev": true }, + "@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "dev": true, + "requires": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "@types/serve-static": { + "version": "1.15.5", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.5.tgz", + "integrity": "sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ==", + "dev": true, + "requires": { + "@types/http-errors": "*", + "@types/mime": "*", + "@types/node": "*" + } + }, "@types/sinonjs__fake-timers": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz", @@ -13632,6 +26046,18 @@ "resolved": "https://registry.npmjs.org/@types/throttle-debounce/-/throttle-debounce-2.1.0.tgz", "integrity": "sha512-5eQEtSCoESnh2FsiLTxE121IiE60hnMqcb435fShf4bpLRjEu1Eoekht23y6zXS9Ts3l+Szu3TARnTsA0GkOkQ==" }, + "@types/unist": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", + "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", + "dev": true + }, + "@types/uuid": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.7.tgz", + "integrity": "sha512-WUtIVRUZ9i5dYXefDEAI7sh9/O7jGvHg7Df/5O/gtH3Yabe5odI3UWopVR1qbPXQtvOxWu3mM4XxlYeZtMWF4g==", + "dev": true + }, "@types/web-bluetooth": { "version": "0.0.16", "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz", @@ -13908,6 +26334,62 @@ "integrity": "sha512-R6JDUfiZbJA9cMiguQ7jxALsgiprjBeHL5ikpXfJCH62pPHtI+JdJ5xWj6Ev73yXSlYl86+blXn1kZHQ7uElxw==", "requires": {} }, + "@vitest/expect": { + "version": "0.34.7", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-0.34.7.tgz", + "integrity": "sha512-G9iEtwrD6ZQ4MVHZufif9Iqz3eLtuwBBNx971fNAGPaugM7ftAWjQN+ob2zWhtzURp8RK3zGXOxVb01mFo3zAQ==", + "dev": true, + "requires": { + "@vitest/spy": "0.34.7", + "@vitest/utils": "0.34.7", + "chai": "^4.3.10" + } + }, + "@vitest/spy": { + "version": "0.34.7", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-0.34.7.tgz", + "integrity": "sha512-NMMSzOY2d8L0mcOt4XcliDOS1ISyGlAXuQtERWVOoVHnKwmG+kKhinAiGw3dTtMQWybfa89FG8Ucg9tiC/FhTQ==", + "dev": true, + "requires": { + "tinyspy": "^2.1.1" + } + }, + "@vitest/utils": { + "version": "0.34.7", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-0.34.7.tgz", + "integrity": "sha512-ziAavQLpCYS9sLOorGrFFKmy2gnfiNU0ZJ15TsMz/K92NAPS/rp9K4z6AJQQk5Y8adCy4Iwpxy7pQumQ/psnRg==", + "dev": true, + "requires": { + "diff-sequences": "^29.4.3", + "loupe": "^2.3.6", + "pretty-format": "^29.5.0" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true + }, + "pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "requires": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + } + }, + "react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + } + } + }, "@vue/compiler-core": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.3.1.tgz", @@ -14268,6 +26750,51 @@ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "peer": true }, + "@yarnpkg/esbuild-plugin-pnp": { + "version": "3.0.0-rc.15", + "resolved": "https://registry.npmjs.org/@yarnpkg/esbuild-plugin-pnp/-/esbuild-plugin-pnp-3.0.0-rc.15.tgz", + "integrity": "sha512-kYzDJO5CA9sy+on/s2aIW0411AklfCi8Ck/4QDivOqsMKpStZA2SsR+X27VTggGwpStWaLrjJcDcdDMowtG8MA==", + "dev": true, + "requires": { + "tslib": "^2.4.0" + } + }, + "@yarnpkg/fslib": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@yarnpkg/fslib/-/fslib-2.10.3.tgz", + "integrity": "sha512-41H+Ga78xT9sHvWLlFOZLIhtU6mTGZ20pZ29EiZa97vnxdohJD2AF42rCoAoWfqUz486xY6fhjMH+DYEM9r14A==", + "dev": true, + "requires": { + "@yarnpkg/libzip": "^2.3.0", + "tslib": "^1.13.0" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } + } + }, + "@yarnpkg/libzip": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/libzip/-/libzip-2.3.0.tgz", + "integrity": "sha512-6xm38yGVIa6mKm/DUCF2zFFJhERh/QWp1ufm4cNUvxsONBmfPg8uZ9pZBdOmF6qFGr/HlT6ABBkCSx/dlEtvWg==", + "dev": true, + "requires": { + "@types/emscripten": "^1.39.6", + "tslib": "^1.13.0" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } + } + }, "accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -14321,6 +26848,18 @@ } } }, + "address": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/address/-/address-1.2.2.tgz", + "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==", + "dev": true + }, + "agent-base": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-5.1.1.tgz", + "integrity": "sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g==", + "dev": true + }, "aggregate-error": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", @@ -14415,6 +26954,12 @@ "picomatch": "^2.0.4" } }, + "app-root-dir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/app-root-dir/-/app-root-dir-1.0.2.tgz", + "integrity": "sha512-jlpIfsOoNoafl92Sz//64uQHGSyMrD2vYG5d8o2a4qGvyNCvXur7bzIsWtAC/6flI2RYAp3kv8rsfBtaLm7w0g==", + "dev": true + }, "arch": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", @@ -14432,6 +26977,15 @@ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, + "aria-hidden": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.3.tgz", + "integrity": "sha512-xcLxITLe2HYa1cnYnwCjkOO1PqUHQpozB8x9AR0OgWN2woOBi5kSDVxKfd0b7sb1hw5qFeJhXm9H1nu3xSfLeQ==", + "dev": true, + "requires": { + "tslib": "^2.0.0" + } + }, "aria-query": { "version": "5.1.3", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", @@ -14449,6 +27003,12 @@ "is-array-buffer": "^3.0.1" } }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "dev": true + }, "array-includes": { "version": "3.1.6", "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", @@ -14501,6 +27061,12 @@ "get-intrinsic": "^1.1.3" } }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "dev": true + }, "asn1": { "version": "0.2.6", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", @@ -14510,12 +27076,46 @@ "safer-buffer": "~2.1.0" } }, + "assert": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-2.1.0.tgz", + "integrity": "sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "is-nan": "^1.3.2", + "object-is": "^1.1.5", + "object.assign": "^4.1.4", + "util": "^0.12.5" + } + }, + "assert-never": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/assert-never/-/assert-never-1.2.1.tgz", + "integrity": "sha512-TaTivMB6pYI1kXwrFlEhLeGfOqoDNdTxjCdwRfFFkEA30Eu+k48W34nlok2EYWJfFFzqaEmichdNM7th6M5HNw==", + "dev": true + }, "assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", "dev": true }, + "assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true + }, + "ast-types": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz", + "integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==", + "dev": true, + "requires": { + "tslib": "^2.0.1" + } + }, "ast-types-flow": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", @@ -14533,6 +27133,12 @@ "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", "dev": true }, + "async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", + "dev": true + }, "async-validator": { "version": "4.2.5", "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-4.2.5.tgz", @@ -14602,6 +27208,13 @@ "deep-equal": "^2.0.5" } }, + "babel-core": { + "version": "7.0.0-bridge.0", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz", + "integrity": "sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==", + "dev": true, + "requires": {} + }, "babel-merge": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/babel-merge/-/babel-merge-3.0.0.tgz", @@ -14618,6 +27231,73 @@ } } }, + "babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + } + }, + "babel-plugin-polyfill-corejs2": { + "version": "0.4.8", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.8.tgz", + "integrity": "sha512-OtIuQfafSzpo/LhnJaykc0R/MMnuLSSVjVYy9mHArIZ9qTCSZ6TpWCuEKZYVoN//t8HqBNScHrOtCrIK5IaGLg==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.5.0", + "semver": "^6.3.1" + } + }, + "babel-plugin-polyfill-corejs3": { + "version": "0.8.7", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.7.tgz", + "integrity": "sha512-KyDvZYxAzkC0Aj2dAPyDzi2Ym15e5JKZSK+maI7NAwSqofvuFglbSsxE7wUOvTg9oFVnHMzVzBKcqEb4PJgtOA==", + "dev": true, + "requires": { + "@babel/helper-define-polyfill-provider": "^0.4.4", + "core-js-compat": "^3.33.1" + }, + "dependencies": { + "@babel/helper-define-polyfill-provider": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.4.tgz", + "integrity": "sha512-QcJMILQCu2jm5TFPGA3lCpJJTeEP+mqeXooG/NZbg/h5FTFi6V0+99ahlRsW8/kRLyb24LZVCCiclDedhLKcBA==", + "dev": true, + "requires": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + } + } + } + }, + "babel-plugin-polyfill-regenerator": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.5.tgz", + "integrity": "sha512-OJGYZlhLqBh2DDHeqAxWB1XIvr49CxiJ2gIt61/PU55CQK4Z58OzMqjDe1zwQdQk+rBYsRc+1rJmdajM3gimHg==", + "dev": true, + "requires": { + "@babel/helper-define-polyfill-provider": "^0.5.0" + } + }, + "babel-walk": { + "version": "3.0.0-canary-5", + "resolved": "https://registry.npmjs.org/babel-walk/-/babel-walk-3.0.0-canary-5.tgz", + "integrity": "sha512-GAwkz0AihzY5bkwIY5QDR+LvsRQgB/B+1foMPvi0FZPMl5fjD7ICiznUiBdLYMH1QYe6vqu4gWYytZOccLouFw==", + "dev": true, + "requires": { + "@babel/types": "^7.9.6" + } + }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -14648,6 +27328,21 @@ "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==" }, + "better-opn": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/better-opn/-/better-opn-3.0.2.tgz", + "integrity": "sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ==", + "dev": true, + "requires": { + "open": "^8.0.4" + } + }, + "big-integer": { + "version": "1.6.52", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", + "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", + "dev": true + }, "big.js": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", @@ -14659,6 +27354,17 @@ "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "devOptional": true }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, "blob-util": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz", @@ -14671,11 +27377,97 @@ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", "dev": true }, + "body-parser": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "dev": true, + "requires": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "dependencies": { + "bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true + }, + "http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, + "requires": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dev": true, + "requires": { + "side-channel": "^1.0.4" + } + }, + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true + } + } + }, "boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" }, + "bplist-parser": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", + "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==", + "dev": true, + "requires": { + "big-integer": "^1.6.44" + } + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -14694,15 +27486,39 @@ "fill-range": "^7.0.1" } }, + "browser-assert": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/browser-assert/-/browser-assert-1.2.1.tgz", + "integrity": "sha512-nfulgvOR6S4gt9UKCeGJOuSGBPGiFT6oQ/2UBnvTY/5aQ1PnksW72fhZkM30DzoRRv2WpwZf1vHHEr3mtuXIWQ==", + "dev": true + }, + "browserify-zlib": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", + "integrity": "sha512-19OEpq7vWgsH6WkvkBJQDFvJS1uPcbFOQ4v9CU839dO+ZZXUZO6XpE6hNCqvlIIj+4fZvRiJ6DsAQ382GwiyTQ==", + "dev": true, + "requires": { + "pako": "~0.2.0" + } + }, "browserslist": { - "version": "4.21.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", - "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", + "version": "4.22.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", + "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", + "requires": { + "caniuse-lite": "^1.0.30001565", + "electron-to-chromium": "^1.4.601", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" + } + }, + "bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, "requires": { - "caniuse-lite": "^1.0.30001449", - "electron-to-chromium": "^1.4.284", - "node-releases": "^2.0.8", - "update-browserslist-db": "^1.0.10" + "node-int64": "^0.4.0" } }, "buffer": { @@ -14726,6 +27542,12 @@ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", + "dev": true + }, "cache-content-type": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-content-type/-/cache-content-type-1.0.1.tgz", @@ -14756,6 +27578,12 @@ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, "camelcase-css": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", @@ -14775,9 +27603,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001503", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001503.tgz", - "integrity": "sha512-Sf9NiF+wZxPfzv8Z3iS0rXM1Do+iOy2Lxvib38glFX+08TCYYYGR5fRJXk4d77C4AYwhUjgYgMsMudbh2TqCKw==" + "version": "1.0.30001580", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001580.tgz", + "integrity": "sha512-mtj5ur2FFPZcCEpXFy8ADXbDACuNFXg6mxVDqp7tqooX6l3zwm+d8EPoeOSIFRDvHs8qu7/SLFOGniULkcH2iA==" }, "case-anything": { "version": "2.1.11", @@ -14790,6 +27618,21 @@ "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", "dev": true }, + "chai": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz", + "integrity": "sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==", + "dev": true, + "requires": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.3", + "deep-eql": "^4.1.3", + "get-func-name": "^2.0.2", + "loupe": "^2.3.6", + "pathval": "^1.1.1", + "type-detect": "^4.0.8" + } + }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -14800,6 +27643,15 @@ "supports-color": "^5.3.0" } }, + "character-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/character-parser/-/character-parser-2.2.0.tgz", + "integrity": "sha512-+UqJQjFEFaTAs3bNsF2j2kEN1baG/zghZbdqoYEDxGZtJo9LBzl1A+m0D4n3qKx8N2FNv8/Xp6yV9mQmBuptaw==", + "dev": true, + "requires": { + "is-regex": "^1.0.3" + } + }, "chart.js": { "version": "3.9.1", "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.9.1.tgz", @@ -14833,6 +27685,15 @@ "date-fns": ">=2.0.0" } }, + "check-error": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", + "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", + "dev": true, + "requires": { + "get-func-name": "^2.0.2" + } + }, "check-more-types": { "version": "2.24.0", "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", @@ -14866,6 +27727,12 @@ } } }, + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true + }, "chrome-trace-event": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", @@ -14878,6 +27745,15 @@ "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", "dev": true }, + "citty": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.5.tgz", + "integrity": "sha512-AS7n5NSc0OQVMV9v6wt3ByujNIrne0/cTjiC2MYqhvao57VNfiuVksTSr2p17nVOhEr2KtqiAkGwHcgMC/qUuQ==", + "dev": true, + "requires": { + "consola": "^3.2.3" + } + }, "clean-stack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", @@ -14893,6 +27769,12 @@ "restore-cursor": "^3.1.0" } }, + "cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "dev": true + }, "cli-table3": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz", @@ -14924,6 +27806,34 @@ "wrap-ansi": "^7.0.0" } }, + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "dev": true + }, + "clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "dependencies": { + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + } + } + }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -14976,11 +27886,114 @@ "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", "dev": true }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "dev": true + }, + "compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dev": true, + "requires": { + "mime-db": ">= 1.43.0 < 2" + } + }, + "compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "dev": true, + "requires": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "concurrently": { "version": "7.6.0", "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-7.6.0.tgz", @@ -15065,6 +28078,22 @@ "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==" }, + "consola": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.2.3.tgz", + "integrity": "sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==", + "dev": true + }, + "constantinople": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-4.0.1.tgz", + "integrity": "sha512-vCrqcSIq4//Gx74TXXCGnHpulY1dskqLTFGDmhrGxzeXL8lF8kvXv6mpNWlJj1uD4DW23D4ljAqbY4RRaaUZIw==", + "dev": true, + "requires": { + "@babel/parser": "^7.6.0", + "@babel/types": "^7.6.1" + } + }, "content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -15081,9 +28110,21 @@ "dev": true }, "convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" + }, + "cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "dev": true + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "dev": true }, "cookies": { "version": "0.8.0", @@ -15108,6 +28149,15 @@ "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.24.1.tgz", "integrity": "sha512-0QTBSYSUZ6Gq21utGzkfITDylE8jWC9Ne1D2MrhvlsZBI1x39OdDIVbzSqtgMndIy6BlHxBXpMGqzZmnztg2rg==" }, + "core-js-compat": { + "version": "3.35.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.35.1.tgz", + "integrity": "sha512-sftHa5qUJY3rs9Zht1WEnmkvXputCyDBczPnr7QDgL8n3qrF3CMXY4VPSYtOLLiOUJcah2WNXREd48iOl6mQIw==", + "dev": true, + "requires": { + "browserslist": "^4.22.2" + } + }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -15147,6 +28197,12 @@ "which": "^2.0.1" } }, + "crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "dev": true + }, "css-declaration-sorter": { "version": "6.4.0", "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.4.0.tgz", @@ -15238,6 +28294,12 @@ "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", "dev": true }, + "css.escape": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", + "dev": true + }, "cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", @@ -15439,12 +28501,6 @@ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true - }, "lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -15454,15 +28510,6 @@ "yallist": "^4.0.0" } }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "requires": { - "path-key": "^3.0.0" - } - }, "semver": { "version": "7.3.8", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", @@ -15563,6 +28610,15 @@ "ms": "2.1.2" } }, + "deep-eql": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", + "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", + "dev": true, + "requires": { + "type-detect": "^4.0.0" + } + }, "deep-equal": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.0.tgz", @@ -15597,6 +28653,25 @@ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==" }, + "default-browser-id": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz", + "integrity": "sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==", + "dev": true, + "requires": { + "bplist-parser": "^0.2.0", + "untildify": "^4.0.0" + } + }, + "defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "dev": true, + "requires": { + "clone": "^1.0.2" + } + }, "define-lazy-prop": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", @@ -15618,6 +28693,28 @@ "integrity": "sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q==", "dev": true }, + "defu": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", + "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", + "dev": true + }, + "del": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/del/-/del-6.1.1.tgz", + "integrity": "sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==", + "dev": true, + "requires": { + "globby": "^11.0.1", + "graceful-fs": "^4.2.4", + "is-glob": "^4.0.1", + "is-path-cwd": "^2.2.0", + "is-path-inside": "^3.0.2", + "p-map": "^4.0.0", + "rimraf": "^3.0.2", + "slash": "^3.0.0" + } + }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -15641,12 +28738,49 @@ "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" }, + "dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true + }, "destroy": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", "dev": true }, + "detect-indent": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", + "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", + "dev": true + }, + "detect-node-es": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", + "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==", + "dev": true + }, + "detect-package-manager": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-package-manager/-/detect-package-manager-2.0.1.tgz", + "integrity": "sha512-j/lJHyoLlWi6G1LDdLgvUtz60Zo5GEj+sVYtTVXnYLDPuzgC3llMxonXym9zIwhhUII8vjdw0LXxavpLqTbl1A==", + "dev": true, + "requires": { + "execa": "^5.1.1" + } + }, + "detect-port": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.5.1.tgz", + "integrity": "sha512-aBzdj76lueB6uUst5iAs7+0H/oOjqI5D16XUWxlWMIMROhcM0rfsNVk93zTngq1dDNpoXRr++Sus7ETAExppAQ==", + "dev": true, + "requires": { + "address": "^1.0.1", + "debug": "4" + } + }, "detective": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.1.tgz", @@ -15664,6 +28798,12 @@ "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", "dev": true }, + "diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true + }, "dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -15687,6 +28827,18 @@ "esutils": "^2.0.2" } }, + "doctypes": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/doctypes/-/doctypes-1.1.0.tgz", + "integrity": "sha512-LLBi6pEqS6Do3EKQ3J0NqHWV5hhb78Pi8vvESYwyOy2c31ZEZVdtitdzsQsKb7878PEERhzUk0ftqGhG6Mz+pQ==", + "dev": true + }, + "dom-accessibility-api": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", + "dev": true + }, "dom-serializer": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", @@ -15737,6 +28889,68 @@ "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==", "dev": true }, + "dotenv-expand": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-10.0.0.tgz", + "integrity": "sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==", + "dev": true + }, + "duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "dev": true, + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -15753,10 +28967,19 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", "dev": true }, + "ejs": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.9.tgz", + "integrity": "sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==", + "dev": true, + "requires": { + "jake": "^10.8.5" + } + }, "electron-to-chromium": { - "version": "1.4.340", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.340.tgz", - "integrity": "sha512-zx8hqumOqltKsv/MF50yvdAlPF9S/4PXbyfzJS6ZGhbddGkRegdwImmfSVqCkEziYzrIGZ/TlrzBND4FysfkDg==" + "version": "1.4.645", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.645.tgz", + "integrity": "sha512-EeS1oQDCmnYsRDRy2zTeC336a/4LZ6WKqvSaM1jLocEk5ZuyszkQtCpsqvuvaIXGOUjwtvF6LTcS8WueibXvSw==" }, "element-plus": { "version": "2.3.1", @@ -15854,6 +29077,21 @@ "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz", "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==" }, + "envinfo": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.11.0.tgz", + "integrity": "sha512-G9/6xF1FPbIw0TtalAMaVPpiq2aDEuKLXM314jPVAO9r2fo2a4BLqMNkmRS7O/xPPZ+COAhGIz3ETvHEV3eUcg==", + "dev": true + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, "es-abstract": { "version": "1.21.2", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz", @@ -15974,6 +29212,21 @@ "@esbuild/win32-x64": "0.18.17" } }, + "esbuild-plugin-alias": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/esbuild-plugin-alias/-/esbuild-plugin-alias-0.2.1.tgz", + "integrity": "sha512-jyfL/pwPqaFXyKnj8lP8iLk6Z0m099uXR45aSN8Av1XD4vhvQutxxPzgA2bTcAwQpa1zCXDcWOlhFgyP3GKqhQ==", + "dev": true + }, + "esbuild-register": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/esbuild-register/-/esbuild-register-3.5.0.tgz", + "integrity": "sha512-+4G/XmakeBAsvJuDugJvtyF1x+XJT4FMocynNpxrvEBViirpfUn2PgNpCHedfWhF4WokNsO/OvMKrmJOIJsI5A==", + "dev": true, + "requires": { + "debug": "^4.3.4" + } + }, "escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -16287,6 +29540,29 @@ } } }, + "eslint-plugin-storybook": { + "version": "0.6.15", + "resolved": "https://registry.npmjs.org/eslint-plugin-storybook/-/eslint-plugin-storybook-0.6.15.tgz", + "integrity": "sha512-lAGqVAJGob47Griu29KXYowI4G7KwMoJDOkEip8ujikuDLxU+oWJ1l0WL6F2oDO4QiyUFXvtDkEkISMOPzo+7w==", + "dev": true, + "requires": { + "@storybook/csf": "^0.0.1", + "@typescript-eslint/utils": "^5.45.0", + "requireindex": "^1.1.0", + "ts-dedent": "^2.2.0" + }, + "dependencies": { + "@storybook/csf": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/@storybook/csf/-/csf-0.0.1.tgz", + "integrity": "sha512-USTLkZze5gkel8MYCujSRBVIrUQ3YPBrLOx7GNk/0wttvVtlzWXAq9eLbQ4p/NicGxP+3T7KPEMVV//g+yubpw==", + "dev": true, + "requires": { + "lodash": "^4.17.15" + } + } + } + }, "eslint-plugin-vue": { "version": "9.10.0", "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.10.0.tgz", @@ -16365,6 +29641,12 @@ "eslint-visitor-keys": "^3.3.0" } }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, "esquery": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", @@ -16396,6 +29678,12 @@ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "dev": true + }, "eventemitter2": { "version": "6.4.7", "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.7.tgz", @@ -16408,6 +29696,31 @@ "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", "peer": true }, + "execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "dependencies": { + "human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true + } + } + }, "executable": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/executable/-/executable-4.1.1.tgz", @@ -16417,6 +29730,102 @@ "pify": "^2.2.0" } }, + "express": { + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "dev": true, + "requires": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.1", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.5.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true + }, + "http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, + "requires": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", + "dev": true + }, + "qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dev": true, + "requires": { + "side-channel": "^1.0.4" + } + }, + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true + } + } + }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -16499,6 +29908,15 @@ "reusify": "^1.0.4" } }, + "fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "requires": { + "bser": "2.1.1" + } + }, "fd-slicer": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", @@ -16508,6 +29926,12 @@ "pend": "~1.2.0" } }, + "fetch-retry": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/fetch-retry/-/fetch-retry-5.0.6.tgz", + "integrity": "sha512-3yurQZ2hD9VISAhJJP9bpYFNQrHHBXE2JxxjY5aLEcDi46RmAzJE2OC9FAde0yis5ElW0jTTzs0zfg/Cca4XqQ==", + "dev": true + }, "figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -16530,6 +29954,64 @@ "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.2.tgz", "integrity": "sha512-Wz3c3XQ5xroCxd1G8b7yL0Ehkf0TC9oYC6buPFkNnU9EnaPlifeAFCyCh+iewXTyFRcg0a6j3J7FmJsIhlhBdw==" }, + "file-system-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/file-system-cache/-/file-system-cache-2.3.0.tgz", + "integrity": "sha512-l4DMNdsIPsVnKrgEXbJwDJsA5mB8rGwHYERMgqQx/xAUtChPJMre1bXBzDEqqVbWv9AIbFezXMxeEkZDSrXUOQ==", + "dev": true, + "requires": { + "fs-extra": "11.1.1", + "ramda": "0.29.0" + }, + "dependencies": { + "fs-extra": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", + "integrity": "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "ramda": { + "version": "0.29.0", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.0.tgz", + "integrity": "sha512-BBea6L67bYLtdbOqfp8f58fPMqEwx0doL+pAi8TZyp2YWz8R9G8z9x75CZI8W+ftqhFHCpEX2cRnUUXK130iKA==", + "dev": true + } + } + }, + "filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dev": true, + "requires": { + "minimatch": "^5.0.1" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -16539,6 +30021,103 @@ "to-regex-range": "^5.0.1" } }, + "finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dev": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true + } + } + }, + "find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + } + } + } + }, "find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -16562,6 +30141,12 @@ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==" }, + "flow-parser": { + "version": "0.227.0", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.227.0.tgz", + "integrity": "sha512-nOygtGKcX/siZK/lFzpfdHEfOkfGcTW7rNroR1Zsz6T/JxSahPALXVt5qVHq/fgvMJuv096BTKbgxN3PzVBaDA==", + "dev": true + }, "flush-promises": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/flush-promises/-/flush-promises-1.0.2.tgz", @@ -16580,6 +30165,24 @@ "is-callable": "^1.1.3" } }, + "foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "dependencies": { + "signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true + } + } + }, "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -16597,6 +30200,12 @@ "mime-types": "^2.1.12" } }, + "forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true + }, "fraction.js": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", @@ -16609,6 +30218,12 @@ "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", "dev": true }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true + }, "fs-extra": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", @@ -16621,6 +30236,32 @@ "universalify": "^2.0.0" } }, + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -16664,6 +30305,12 @@ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true }, + "get-func-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", + "dev": true + }, "get-intrinsic": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", @@ -16674,6 +30321,36 @@ "has-symbols": "^1.0.3" } }, + "get-nonce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz", + "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==", + "dev": true + }, + "get-npm-tarball-url": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/get-npm-tarball-url/-/get-npm-tarball-url-2.1.0.tgz", + "integrity": "sha512-ro+DiMu5DXgRBabqXupW38h7WPZ9+Ad8UjwhvsmmN8w1sU7ab0nzAXvVZ4kqYg57OrqomRtJvepX5/xvFKNtjA==", + "dev": true + }, + "get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true + }, + "get-port": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz", + "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==", + "dev": true + }, + "get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true + }, "get-symbol-description": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", @@ -16701,6 +30378,28 @@ "assert-plus": "^1.0.0" } }, + "giget": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/giget/-/giget-1.2.1.tgz", + "integrity": "sha512-4VG22mopWtIeHwogGSy1FViXVo0YT+m6BrqZfz0JJFwbSsePsCdOzdLIIli5BtMp7Xe8f/o2OmBpQX2NBOC24g==", + "dev": true, + "requires": { + "citty": "^0.1.5", + "consola": "^3.2.3", + "defu": "^6.1.3", + "node-fetch-native": "^1.6.1", + "nypm": "^0.3.3", + "ohash": "^1.1.3", + "pathe": "^1.1.1", + "tar": "^6.2.0" + } + }, + "github-slugger": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.5.0.tgz", + "integrity": "sha512-wIh+gKBI9Nshz2o46B0B3f5k/W+WI9ZAv6y5Dn5WJ5SK1t0TnDimB4WE5rmTD05ZAIn8HALCZVmCsvj0w0v0lw==", + "dev": true + }, "glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -16725,8 +30424,7 @@ "glob-to-regexp": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "peer": true + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" }, "global-dirs": { "version": "3.0.1", @@ -16782,6 +30480,33 @@ "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==" }, + "gunzip-maybe": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/gunzip-maybe/-/gunzip-maybe-1.4.2.tgz", + "integrity": "sha512-4haO1M4mLO91PW57BMsDFf75UmwoRX0GkdD+Faw+Lr+r/OZrOCS0pIBwOL1xCKQqnQzbNFGgK2V2CpBUPeFNTw==", + "dev": true, + "requires": { + "browserify-zlib": "^0.1.4", + "is-deflate": "^1.0.0", + "is-gzip": "^1.0.0", + "peek-stream": "^1.1.0", + "pumpify": "^1.3.3", + "through2": "^2.0.3" + } + }, + "handlebars": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4", + "wordwrap": "^1.0.0" + } + }, "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -16831,6 +30556,12 @@ "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-2.0.0.tgz", "integrity": "sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==" }, + "hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, "http-assert": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/http-assert/-/http-assert-1.5.0.tgz", @@ -16873,12 +30604,31 @@ "sshpk": "^1.14.1" } }, + "https-proxy-agent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz", + "integrity": "sha512-zoDhWrkR3of1l9QAL8/scJZyLu8j/gBkcwcaQOZh7Gyh/+uJQzGVETdgT30akuwkpL8HTRfssqI3BZuV18teDg==", + "dev": true, + "requires": { + "agent-base": "5", + "debug": "4" + } + }, "human-signals": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", "dev": true }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, "ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -16946,6 +30696,33 @@ "side-channel": "^1.0.4" } }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "requires": { + "loose-envify": "^1.0.0" + } + }, + "ip": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", + "dev": true + }, + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true + }, + "is-absolute-url": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz", + "integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==", + "dev": true + }, "is-arguments": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", @@ -16965,6 +30742,12 @@ "is-typed-array": "^1.1.10" } }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, "is-bigint": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", @@ -17021,12 +30804,36 @@ "has-tostringtag": "^1.0.0" } }, + "is-deflate": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-deflate/-/is-deflate-1.0.0.tgz", + "integrity": "sha512-YDoFpuZWu1VRXlsnlYMzKyVRITXj7Ej/V9gXQ2/pAe7X1J7M/RNOqaIYi6qUn+B7nGyB9pDXrv02dsB58d2ZAQ==", + "dev": true + }, "is-docker": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", "dev": true }, + "is-expression": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-expression/-/is-expression-4.0.0.tgz", + "integrity": "sha512-zMIXX63sxzG3XrkHkrAPvm/OVZVSCPNkwMHU8oTX7/U3AL78I0QXCEICXUM13BIa8TYGZ68PiTKfQz3yaTNr4A==", + "dev": true, + "requires": { + "acorn": "^7.1.1", + "object-assign": "^4.1.1" + }, + "dependencies": { + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + } + } + }, "is-extendable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", @@ -17073,6 +30880,12 @@ "is-extglob": "^2.1.1" } }, + "is-gzip": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-gzip/-/is-gzip-1.0.0.tgz", + "integrity": "sha512-rcfALRIb1YewtnksfRIHGcIY93QnK8BIQ/2c9yDYcG/Y6+vRoJuTWBmmSEbyLLYtXm7q35pHOHbZFQBaLrhlWQ==", + "dev": true + }, "is-installed-globally": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", @@ -17083,11 +30896,27 @@ "is-path-inside": "^3.0.2" } }, + "is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "dev": true + }, "is-map": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==" }, + "is-nan": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", + "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + } + }, "is-negative-zero": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", @@ -17107,6 +30936,12 @@ "has-tostringtag": "^1.0.0" } }, + "is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", + "dev": true + }, "is-path-inside": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", @@ -17117,6 +30952,12 @@ "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==" }, + "is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", + "dev": true + }, "is-regex": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", @@ -17139,6 +30980,12 @@ "call-bind": "^1.0.2" } }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true + }, "is-string": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", @@ -17231,13 +31078,214 @@ "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", "dev": true }, + "istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "requires": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + } + }, + "jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dev": true, + "requires": { + "@isaacs/cliui": "^8.0.2", + "@pkgjs/parseargs": "^0.11.0" + } + }, + "jake": { + "version": "10.8.7", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.7.tgz", + "integrity": "sha512-ZDi3aP+fG/LchyBzUM804VjddnwfSfsdeYkwt8NcbKRvo4rFkjhs456iLFn3k2ZUWvNe4i48WACDbza8fhq2+w==", + "dev": true, + "requires": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.4", + "minimatch": "^3.1.2" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "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 + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "fsevents": "^2.3.2", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + } + }, + "jest-mock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", + "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", + "dev": true, + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "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 + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "dev": true + }, "jest-util": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.5.0.tgz", - "integrity": "sha512-RYMgG/MTadOr5t8KdhejfvUU82MxsCu5MF6KuDUHl+NuwzUt+Sm6jJWxTJVrDR1j5M/gJVCPKQEpWXY+yIQ6lQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, "requires": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -17297,13 +31345,13 @@ } }, "jest-worker": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.5.0.tgz", - "integrity": "sha512-NcrQnevGoSp4b5kg+akIpthoAFHxPBcb5P6mYPY0fUNT+sSvmtu6jlkEle3anczUKIKEbMxFimk9oTP/tpIPgA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", "dev": true, "requires": { "@types/node": "*", - "jest-util": "^29.5.0", + "jest-util": "^29.7.0", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, @@ -17343,6 +31391,12 @@ "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.4.0.tgz", "integrity": "sha512-FfVSdx6pJ41Oa+CF7RDaFmTnCaFhua+SNYQX74riGOpl96x+2jQCqEfQ2bnXu/5DPCqlRuiqyvTJM0Qjz26IVg==" }, + "js-stringify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/js-stringify/-/js-stringify-1.0.2.tgz", + "integrity": "sha512-rtS5ATOo2Q5k1G+DADISilDA6lv79zIiwFd6CcjuIxGKLFm5C+RLImRscVap9k55i+MOZwgliw+NejvkLuGD5g==", + "dev": true + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -17362,6 +31416,96 @@ "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", "dev": true }, + "jscodeshift": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.15.1.tgz", + "integrity": "sha512-hIJfxUy8Rt4HkJn/zZPU9ChKfKZM1342waJ1QC2e2YsPcWhM+3BJ4dcfQCzArTrk1jJeNLB341H+qOcEHRxJZg==", + "dev": true, + "requires": { + "@babel/core": "^7.23.0", + "@babel/parser": "^7.23.0", + "@babel/plugin-transform-class-properties": "^7.22.5", + "@babel/plugin-transform-modules-commonjs": "^7.23.0", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.22.11", + "@babel/plugin-transform-optional-chaining": "^7.23.0", + "@babel/plugin-transform-private-methods": "^7.22.5", + "@babel/preset-flow": "^7.22.15", + "@babel/preset-typescript": "^7.23.0", + "@babel/register": "^7.22.15", + "babel-core": "^7.0.0-bridge.0", + "chalk": "^4.1.2", + "flow-parser": "0.*", + "graceful-fs": "^4.2.4", + "micromatch": "^4.0.4", + "neo-async": "^2.5.0", + "node-dir": "^0.1.17", + "recast": "^0.23.3", + "temp": "^0.8.4", + "write-file-atomic": "^2.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "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 + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "write-file-atomic": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + } + } + }, "jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -17370,8 +31514,7 @@ "json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "peer": true + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, "json-schema": { "version": "0.4.0", @@ -17428,6 +31571,16 @@ "verror": "1.10.0" } }, + "jstransformer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-1.0.0.tgz", + "integrity": "sha512-C9YK3Rf8q6VAPDCCU9fnqo3mAfOH6vUGnMcP4AQAYIEpWtfGLpwOTmZ+igtdK5y+VvI2n3CyYSzy4Qh34eq24A==", + "dev": true, + "requires": { + "is-promise": "^2.0.0", + "promise": "^7.0.1" + } + }, "jsx-ast-utils": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz", @@ -17446,6 +31599,18 @@ "tsscmp": "1.0.6" } }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true + }, "koa": { "version": "2.14.1", "resolved": "https://registry.npmjs.org/koa/-/koa-2.14.1.tgz", @@ -17552,6 +31717,23 @@ "integrity": "sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw==", "dev": true }, + "lazy-universal-dotenv": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/lazy-universal-dotenv/-/lazy-universal-dotenv-4.0.0.tgz", + "integrity": "sha512-aXpZJRnTkpK6gQ/z4nk+ZBLd/Qdp118cvPruLSIQzQNRhKwEcdXCOzXuF55VDqIiuAaY3UGZ10DJtvZzDcvsxg==", + "dev": true, + "requires": { + "app-root-dir": "^1.0.2", + "dotenv": "^16.0.0", + "dotenv-expand": "^10.0.0" + } + }, + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true + }, "levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -17567,6 +31749,12 @@ "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", "dev": true }, + "lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, "linkify-it": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-4.0.1.tgz", @@ -17632,6 +31820,12 @@ "integrity": "sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ==", "requires": {} }, + "lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "dev": true + }, "lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -17794,6 +31988,15 @@ "js-tokens": "^3.0.0 || ^4.0.0" } }, + "loupe": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", + "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", + "dev": true, + "requires": { + "get-func-name": "^2.0.1" + } + }, "lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -17802,6 +32005,12 @@ "yallist": "^3.0.2" } }, + "lz-string": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "dev": true + }, "magic-string": { "version": "0.30.0", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.0.tgz", @@ -17810,11 +32019,35 @@ "@jridgewell/sourcemap-codec": "^1.4.13" } }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "requires": { + "semver": "^6.0.0" + } + }, "make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" }, + "makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "requires": { + "tmpl": "1.0.5" + } + }, + "map-or-similar": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/map-or-similar/-/map-or-similar-1.5.0.tgz", + "integrity": "sha512-0aF7ZmVon1igznGI4VS30yugpduQW3y3GkcgGJOp7d8x8QrizhigUxjI/m2UojsXXto+jLAH3KSz+xOJTiORjg==", + "dev": true + }, "markdown-it": { "version": "13.0.1", "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-13.0.1.tgz", @@ -17827,11 +32060,33 @@ "uc.micro": "^1.0.5" } }, + "markdown-to-jsx": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-7.4.0.tgz", + "integrity": "sha512-zilc+MIkVVXPyTb4iIUTIz9yyqfcWjszGXnwF9K/aiBWcHXFcmdEMTkG01/oQhwSCH7SY1BnG6+ev5BzWmbPrg==", + "dev": true, + "requires": {} + }, "marked": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==" }, + "mdast-util-definitions": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-4.0.0.tgz", + "integrity": "sha512-k8AJ6aNnUkB7IE+5azR9h81O5EQ/cTDXtWdMq9Kk5KcEW/8ritU5CeLg/9HhOC++nALHBlaogJ5jz0Ybk3kPMQ==", + "dev": true, + "requires": { + "unist-util-visit": "^2.0.0" + } + }, + "mdast-util-to-string": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-1.1.0.tgz", + "integrity": "sha512-jVU0Nr2B9X3MU4tSK7JP1CMkSvOj7X5l/GboG1tKRw52lLF1x2Ju92Ms9tNetCcbfX3hzlM73zYo2NKkWSfF/A==", + "dev": true + }, "mdn-data": { "version": "2.0.14", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", @@ -17854,6 +32109,21 @@ "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==" }, + "memoizerific": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/memoizerific/-/memoizerific-1.11.3.tgz", + "integrity": "sha512-/EuHYwAPdLtXwAwSZkh/Gutery6pD2KYd44oQLhAvQp/50mpyduZh8Q7PYHXTCJ+wuXxt7oij2LXyIJOOYFPog==", + "dev": true, + "requires": { + "map-or-similar": "^1.5.0" + } + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", + "dev": true + }, "merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -17881,6 +32151,12 @@ "picomatch": "^2.3.1" } }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true + }, "mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", @@ -17900,6 +32176,12 @@ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true }, + "min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true + }, "mini-css-extract-plugin": { "version": "2.7.5", "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.5.tgz", @@ -17963,6 +32245,39 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" }, + "minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true + }, + "minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, "mitt": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.0.tgz", @@ -17977,6 +32292,12 @@ "minimist": "^1.2.6" } }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "dev": true + }, "mlly": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.2.0.tgz", @@ -18029,8 +32350,16 @@ "neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "peer": true + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + }, + "node-dir": { + "version": "0.1.17", + "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz", + "integrity": "sha512-tmPX422rYgofd4epzrNoOXiE8XFZYOcCq1vD7MAXCDO+O+zndlA2ztdKKMa+EeuBG5tHETpr4ml4RGgpqDCCAg==", + "dev": true, + "requires": { + "minimatch": "^3.0.2" + } }, "node-emoji": { "version": "1.11.0", @@ -18048,10 +32377,42 @@ "whatwg-url": "^5.0.0" } }, + "node-fetch-native": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.1.tgz", + "integrity": "sha512-bW9T/uJDPAJB2YNYEpWzE54U5O3MQidXsOyTfnbKYtTtFexRvGzb1waphBN4ZwP6EcIvYYEOwW0b72BpAqydTw==", + "dev": true + }, + "node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true + }, "node-releases": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", - "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==" + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" + }, + "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" + }, + "dependencies": { + "semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true + } + } }, "normalize-path": { "version": "3.0.0", @@ -18076,6 +32437,15 @@ "resolved": "https://registry.npmjs.org/normalize-wheel-es/-/normalize-wheel-es-1.2.0.tgz", "integrity": "sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw==" }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + }, "nprogress": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz", @@ -18089,6 +32459,97 @@ "boolbase": "^1.0.0" } }, + "nypm": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.3.6.tgz", + "integrity": "sha512-2CATJh3pd6CyNfU5VZM7qSwFu0ieyabkEdnogE30Obn1czrmOYiZ8DOZLe1yBdLKWoyD3Mcy2maUs+0MR3yVjQ==", + "dev": true, + "requires": { + "citty": "^0.1.5", + "execa": "^8.0.1", + "pathe": "^1.1.2", + "ufo": "^1.3.2" + }, + "dependencies": { + "execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + } + }, + "get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true + }, + "human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true + }, + "is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true + }, + "mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true + }, + "npm-run-path": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.2.0.tgz", + "integrity": "sha512-W4/tgAXFqFA0iL7fk0+uQ3g7wkL8xJmx3XdK0VGb4cHW//eZTtKGvFBBoRKVTpY7n6ze4NL9ly7rgXcHufqXKg==", + "dev": true, + "requires": { + "path-key": "^4.0.0" + } + }, + "onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "requires": { + "mimic-fn": "^4.0.0" + } + }, + "path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true + }, + "signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true + }, + "strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true + } + } + }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -18185,6 +32646,12 @@ "es-abstract": "^1.20.4" } }, + "ohash": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-1.1.3.tgz", + "integrity": "sha512-zuHHiGTYTA1sYJ/wZN+t5HKZaH23i4yI1HMwbuXm24Nid7Dv0KcuRlKoNKS9UNfAVSBlnGLcuQrnOKWOZoEGaw==", + "dev": true + }, "on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -18194,6 +32661,12 @@ "ee-first": "1.1.1" } }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "dev": true + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -18241,6 +32714,74 @@ "word-wrap": "^1.2.3" } }, + "ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dev": true, + "requires": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "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 + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "orderedmap": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/orderedmap/-/orderedmap-2.1.0.tgz", @@ -18277,6 +32818,18 @@ "aggregate-error": "^3.0.0" } }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==", + "dev": true + }, "papaparse": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/papaparse/-/papaparse-5.4.1.tgz", @@ -18290,6 +32843,18 @@ "callsites": "^3.0.0" } }, + "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" + } + }, "parse-srcset": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/parse-srcset/-/parse-srcset-1.0.2.tgz", @@ -18321,6 +32886,24 @@ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, + "path-scurry": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "dev": true, + "requires": { + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.1.0.tgz", + "integrity": "sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==", + "dev": true + } + } + }, "path-to-regexp": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz", @@ -18334,11 +32917,28 @@ "dev": true }, "pathe": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.0.tgz", - "integrity": "sha512-ODbEPR0KKHqECXW1GoxdDb+AZvULmXjVPy4rt+pGo2+TnjJTIPJQSVS6N63n8T2Ip+syHhbn52OewKicV0373w==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "dev": true + }, + "pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", "dev": true }, + "peek-stream": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/peek-stream/-/peek-stream-1.1.3.tgz", + "integrity": "sha512-FhJ+YbOSBb9/rIl2ZeE/QHEsWn7PqNYt8ARAY3kIgNGOk13g9FGyIY6JIl/xB/3TFRVoTv5as0l11weORrTekA==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "duplexify": "^3.5.0", + "through2": "^2.0.3" + } + }, "pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", @@ -18385,6 +32985,21 @@ } } }, + "pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true + }, + "pkg-dir": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", + "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", + "dev": true, + "requires": { + "find-up": "^5.0.0" + } + }, "pkg-types": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.0.2.tgz", @@ -18401,6 +33016,15 @@ "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==" }, + "polished": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/polished/-/polished-4.2.2.tgz", + "integrity": "sha512-Sz2Lkdxz6F2Pgnpi9U5Ng/WdWAUZxmHrNPoVlm3aAemxoy2Qy7LGjQg4uf8qKelDAUW94F4np3iH2YPf2qefcQ==", + "dev": true, + "requires": { + "@babel/runtime": "^7.17.8" + } + }, "portfinder": { "version": "1.0.32", "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.32.tgz", @@ -18752,12 +33376,86 @@ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==" }, + "prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "dev": true + }, "pretty-bytes": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", "dev": true }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + } + } + }, + "pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==", + "dev": true + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, + "promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "dev": true, + "requires": { + "asap": "~2.0.3" + } + }, + "prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "requires": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + } + }, "prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", @@ -18953,6 +33651,16 @@ "prosemirror-transform": "^1.1.0" } }, + "proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, + "requires": { + "forwarded": "0.2.0", + "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", @@ -18965,6 +33673,130 @@ "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", "dev": true }, + "pug": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pug/-/pug-3.0.2.tgz", + "integrity": "sha512-bp0I/hiK1D1vChHh6EfDxtndHji55XP/ZJKwsRqrz6lRia6ZC2OZbdAymlxdVFwd1L70ebrVJw4/eZ79skrIaw==", + "dev": true, + "requires": { + "pug-code-gen": "^3.0.2", + "pug-filters": "^4.0.0", + "pug-lexer": "^5.0.1", + "pug-linker": "^4.0.0", + "pug-load": "^3.0.0", + "pug-parser": "^6.0.0", + "pug-runtime": "^3.0.1", + "pug-strip-comments": "^2.0.0" + } + }, + "pug-attrs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pug-attrs/-/pug-attrs-3.0.0.tgz", + "integrity": "sha512-azINV9dUtzPMFQktvTXciNAfAuVh/L/JCl0vtPCwvOA21uZrC08K/UnmrL+SXGEVc1FwzjW62+xw5S/uaLj6cA==", + "dev": true, + "requires": { + "constantinople": "^4.0.1", + "js-stringify": "^1.0.2", + "pug-runtime": "^3.0.0" + } + }, + "pug-code-gen": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pug-code-gen/-/pug-code-gen-3.0.2.tgz", + "integrity": "sha512-nJMhW16MbiGRiyR4miDTQMRWDgKplnHyeLvioEJYbk1RsPI3FuA3saEP8uwnTb2nTJEKBU90NFVWJBk4OU5qyg==", + "dev": true, + "requires": { + "constantinople": "^4.0.1", + "doctypes": "^1.1.0", + "js-stringify": "^1.0.2", + "pug-attrs": "^3.0.0", + "pug-error": "^2.0.0", + "pug-runtime": "^3.0.0", + "void-elements": "^3.1.0", + "with": "^7.0.0" + } + }, + "pug-error": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pug-error/-/pug-error-2.0.0.tgz", + "integrity": "sha512-sjiUsi9M4RAGHktC1drQfCr5C5eriu24Lfbt4s+7SykztEOwVZtbFk1RRq0tzLxcMxMYTBR+zMQaG07J/btayQ==", + "dev": true + }, + "pug-filters": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pug-filters/-/pug-filters-4.0.0.tgz", + "integrity": "sha512-yeNFtq5Yxmfz0f9z2rMXGw/8/4i1cCFecw/Q7+D0V2DdtII5UvqE12VaZ2AY7ri6o5RNXiweGH79OCq+2RQU4A==", + "dev": true, + "requires": { + "constantinople": "^4.0.1", + "jstransformer": "1.0.0", + "pug-error": "^2.0.0", + "pug-walk": "^2.0.0", + "resolve": "^1.15.1" + } + }, + "pug-lexer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/pug-lexer/-/pug-lexer-5.0.1.tgz", + "integrity": "sha512-0I6C62+keXlZPZkOJeVam9aBLVP2EnbeDw3An+k0/QlqdwH6rv8284nko14Na7c0TtqtogfWXcRoFE4O4Ff20w==", + "dev": true, + "requires": { + "character-parser": "^2.2.0", + "is-expression": "^4.0.0", + "pug-error": "^2.0.0" + } + }, + "pug-linker": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pug-linker/-/pug-linker-4.0.0.tgz", + "integrity": "sha512-gjD1yzp0yxbQqnzBAdlhbgoJL5qIFJw78juN1NpTLt/mfPJ5VgC4BvkoD3G23qKzJtIIXBbcCt6FioLSFLOHdw==", + "dev": true, + "requires": { + "pug-error": "^2.0.0", + "pug-walk": "^2.0.0" + } + }, + "pug-load": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pug-load/-/pug-load-3.0.0.tgz", + "integrity": "sha512-OCjTEnhLWZBvS4zni/WUMjH2YSUosnsmjGBB1An7CsKQarYSWQ0GCVyd4eQPMFJqZ8w9xgs01QdiZXKVjk92EQ==", + "dev": true, + "requires": { + "object-assign": "^4.1.1", + "pug-walk": "^2.0.0" + } + }, + "pug-parser": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/pug-parser/-/pug-parser-6.0.0.tgz", + "integrity": "sha512-ukiYM/9cH6Cml+AOl5kETtM9NR3WulyVP2y4HOU45DyMim1IeP/OOiyEWRr6qk5I5klpsBnbuHpwKmTx6WURnw==", + "dev": true, + "requires": { + "pug-error": "^2.0.0", + "token-stream": "1.0.0" + } + }, + "pug-runtime": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/pug-runtime/-/pug-runtime-3.0.1.tgz", + "integrity": "sha512-L50zbvrQ35TkpHwv0G6aLSuueDRwc/97XdY8kL3tOT0FmhgG7UypU3VztfV/LATAvmUfYi4wNxSajhSAeNN+Kg==", + "dev": true + }, + "pug-strip-comments": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pug-strip-comments/-/pug-strip-comments-2.0.0.tgz", + "integrity": "sha512-zo8DsDpH7eTkPHCXFeAk1xZXJbyoTfdPlNR0bK7rpOMuhBYb0f5qUVCO1xlsitYd3w5FQTK7zpNVKb3rZoUrrQ==", + "dev": true, + "requires": { + "pug-error": "^2.0.0" + } + }, + "pug-walk": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pug-walk/-/pug-walk-2.0.0.tgz", + "integrity": "sha512-yYELe9Q5q9IQhuvqsZNwA5hfPkMJ8u92bQLIMcsMxf/VADjNtEYptU+inlufAFYcWdHlwNfZOEnOOQrZrcyJCQ==", + "dev": true + }, "pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", @@ -18975,11 +33807,107 @@ "once": "^1.3.1" } }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + }, + "dependencies": { + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, "punycode": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==" }, + "puppeteer-core": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-2.1.1.tgz", + "integrity": "sha512-n13AWriBMPYxnpbb6bnaY5YoY6rGj8vPLrz6CZF3o0qJNEwlcfJVxBzYZ0NJsQ21UbdJoijPCDrM++SUVEz7+w==", + "dev": true, + "requires": { + "@types/mime-types": "^2.1.0", + "debug": "^4.1.0", + "extract-zip": "^1.6.6", + "https-proxy-agent": "^4.0.0", + "mime": "^2.0.3", + "mime-types": "^2.1.25", + "progress": "^2.0.1", + "proxy-from-env": "^1.0.0", + "rimraf": "^2.6.1", + "ws": "^6.1.0" + }, + "dependencies": { + "extract-zip": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz", + "integrity": "sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==", + "dev": true, + "requires": { + "concat-stream": "^1.6.2", + "debug": "^2.6.9", + "mkdirp": "^0.5.4", + "yauzl": "^2.10.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "ws": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz", + "integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0" + } + } + } + }, "qs": { "version": "6.11.1", "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.1.tgz", @@ -19012,11 +33940,122 @@ "safe-buffer": "^5.1.0" } }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true + }, + "raw-body": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "dev": true, + "requires": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "dependencies": { + "bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true + }, + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true + }, + "http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, + "requires": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + } + }, + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true + } + } + }, + "react": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "dev": true, + "requires": { + "loose-envify": "^1.1.0" + } + }, + "react-colorful": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/react-colorful/-/react-colorful-5.6.1.tgz", + "integrity": "sha512-1exovf0uGTGyq5mXQT0zgQ80uvj2PCwvF8zY1RN9/vbJVSjSo3fsB/4L3ObbF7u70NduSiK4xu4Y6q1MHoUGEw==", + "dev": true, + "requires": {} + }, + "react-dom": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", + "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "dev": true, + "requires": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.0" + } + }, "react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, + "react-remove-scroll": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.5.5.tgz", + "integrity": "sha512-ImKhrzJJsyXJfBZ4bzu8Bwpka14c/fQt0k+cyFp/PBhTfyDnU5hjOtM4AG/0AMyy8oKzOTR0lDgJIM7pYXI0kw==", + "dev": true, + "requires": { + "react-remove-scroll-bar": "^2.3.3", + "react-style-singleton": "^2.2.1", + "tslib": "^2.1.0", + "use-callback-ref": "^1.3.0", + "use-sidecar": "^1.1.2" + } + }, + "react-remove-scroll-bar": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.4.tgz", + "integrity": "sha512-63C4YQBUt0m6ALadE9XV56hV8BgJWDmmTPY758iIJjfQKt2nYwoUrPk0LXRXcB/yIj82T1/Ixfdpdk68LwIB0A==", + "dev": true, + "requires": { + "react-style-singleton": "^2.2.1", + "tslib": "^2.0.0" + } + }, + "react-style-singleton": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.1.tgz", + "integrity": "sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==", + "dev": true, + "requires": { + "get-nonce": "^1.0.0", + "invariant": "^2.2.4", + "tslib": "^2.0.0" + } + }, "read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", @@ -19026,13 +34065,138 @@ "pify": "^2.3.0" } }, - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "devOptional": true, + "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" + }, + "dependencies": { + "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 + } + } + }, + "read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "requires": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + } + } + }, + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "devOptional": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "recast": { + "version": "0.23.4", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.4.tgz", + "integrity": "sha512-qtEDqIZGVcSZCHniWwZWbRy79Dc6Wp3kT/UmDA2RJKBPg7+7k51aQBZirHmUGn5uvHf2rg8DkjizrN26k61ATw==", + "dev": true, + "requires": { + "assert": "^2.0.0", + "ast-types": "^0.16.1", + "esprima": "~4.0.0", + "source-map": "~0.6.1", + "tslib": "^2.0.1" + } + }, + "redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "requires": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + } + }, + "regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true + }, + "regenerate-unicode-properties": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", + "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", + "dev": true, "requires": { - "picomatch": "^2.2.1" + "regenerate": "^1.4.2" } }, "regenerator-runtime": { @@ -19040,6 +34204,15 @@ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" }, + "regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "dev": true, + "requires": { + "@babel/runtime": "^7.8.4" + } + }, "regexp.prototype.flags": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", @@ -19050,6 +34223,61 @@ "functions-have-names": "^1.2.2" } }, + "regexpu-core": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", + "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "dev": true, + "requires": { + "@babel/regjsgen": "^0.8.0", + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.1.0", + "regjsparser": "^0.9.1", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + } + }, + "regjsparser": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "dev": true, + "requires": { + "jsesc": "~0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "dev": true + } + } + }, + "remark-external-links": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/remark-external-links/-/remark-external-links-8.0.0.tgz", + "integrity": "sha512-5vPSX0kHoSsqtdftSHhIYofVINC8qmp0nctkeU9YoJwV3YfiBRiI6cbFRJ0oI/1F9xS+bopXG0m2KS8VFscuKA==", + "dev": true, + "requires": { + "extend": "^3.0.0", + "is-absolute-url": "^3.0.0", + "mdast-util-definitions": "^4.0.0", + "space-separated-tokens": "^1.0.0", + "unist-util-visit": "^2.0.0" + } + }, + "remark-slug": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/remark-slug/-/remark-slug-6.1.0.tgz", + "integrity": "sha512-oGCxDF9deA8phWvxFuyr3oSJsdyUAxMFbA0mZ7Y1Sas+emILtO+e5WutF9564gDsEN4IXaQXm5pFo6MLH+YmwQ==", + "dev": true, + "requires": { + "github-slugger": "^1.0.0", + "mdast-util-to-string": "^1.0.0", + "unist-util-visit": "^2.0.0" + } + }, "replace-in-file": { "version": "6.3.5", "resolved": "https://registry.npmjs.org/replace-in-file/-/replace-in-file-6.3.5.tgz", @@ -19133,6 +34361,12 @@ "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", "dev": true }, + "requireindex": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz", + "integrity": "sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==", + "dev": true + }, "resolve": { "version": "1.22.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", @@ -19359,6 +34593,15 @@ "source-map-js": ">=0.6.2 <2.0.0" } }, + "scheduler": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", + "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", + "dev": true, + "requires": { + "loose-envify": "^1.1.0" + } + }, "scule": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/scule/-/scule-1.0.0.tgz", @@ -19366,9 +34609,80 @@ "dev": true }, "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + }, + "send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dev": true, + "requires": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + } + } + }, + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true + }, + "http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, + "requires": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true + } + } }, "serialize-javascript": { "version": "6.0.1", @@ -19378,12 +34692,33 @@ "randombytes": "^2.1.0" } }, + "serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dev": true, + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + } + }, "setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", "dev": true }, + "shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "requires": { + "kind-of": "^6.0.2" + } + }, "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -19419,6 +34754,12 @@ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true }, + "sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, "slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -19506,12 +34847,56 @@ "source-map": "^0.6.0" } }, + "space-separated-tokens": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz", + "integrity": "sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==", + "dev": true + }, "spawn-command": { "version": "0.0.2-1", "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz", "integrity": "sha512-n98l9E2RMSJ9ON1AKisHzz7V42VDiBQGY6PB1BwRglz99wpVsSuGzQ+jOi6lFXBGVTCrRpltvjm+/XA+tpeJrg==", "dev": true }, + "spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.4.0.tgz", + "integrity": "sha512-hcjppoJ68fhxA/cjbN4T8N6uCUejN8yFw69ttpqtBeCbF3u13n7mb31NB9jKwGTTWWnt9IbRA/mf1FprYS8wfw==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.16", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.16.tgz", + "integrity": "sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==", + "dev": true + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, "sshpk": { "version": "1.17.0", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", @@ -19549,6 +34934,36 @@ "internal-slot": "^1.0.4" } }, + "store2": { + "version": "2.14.2", + "resolved": "https://registry.npmjs.org/store2/-/store2-2.14.2.tgz", + "integrity": "sha512-siT1RiqlfQnGqgT/YzXVUNsom9S0H1OX+dpdGN1xkyYATo4I6sep5NmsRD/40s3IIOvlCq6akxkqG82urIZW1w==", + "dev": true + }, + "storybook": { + "version": "7.6.10", + "resolved": "https://registry.npmjs.org/storybook/-/storybook-7.6.10.tgz", + "integrity": "sha512-ypFeGhQTUBBfqSUVZYh7wS5ghn3O2wILCiQc4459SeUpvUn+skcqw/TlrwGSoF5EWjDA7gtRrWDxO3mnlPt5Cw==", + "dev": true, + "requires": { + "@storybook/cli": "7.6.10" + } + }, + "stream-shift": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz", + "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==", + "dev": true + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "requires": { + "safe-buffer": "~5.2.0" + } + }, "string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -19568,6 +34983,25 @@ } } }, + "string-width-cjs": { + "version": "npm:string-width@4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "dependencies": { + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + } + } + }, "string.prototype.matchall": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz", @@ -19621,6 +35055,15 @@ "ansi-regex": "^5.0.1" } }, + "strip-ansi-cjs": { + "version": "npm:strip-ansi@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": "^5.0.1" + } + }, "strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", @@ -19632,6 +35075,15 @@ "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", "dev": true }, + "strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "requires": { + "min-indent": "^1.0.0" + } + }, "strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -19692,6 +35144,12 @@ } } }, + "synchronous-promise": { + "version": "2.0.17", + "resolved": "https://registry.npmjs.org/synchronous-promise/-/synchronous-promise-2.0.17.tgz", + "integrity": "sha512-AsS729u2RHUfEra9xJrE39peJcc2stq2+poBXX8bcM08Y6g9j/i/PUzwNQqkaJde7Ntg1TO7bSREbR5sdosQ+g==", + "dev": true + }, "tailwind-config-viewer": { "version": "1.7.2", "resolved": "https://registry.npmjs.org/tailwind-config-viewer/-/tailwind-config-viewer-1.7.2.tgz", @@ -19708,69 +35166,186 @@ "replace-in-file": "^6.1.0" }, "dependencies": { - "commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", - "dev": true - }, - "open": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", - "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", + "commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "dev": true + }, + "open": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", + "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", + "dev": true, + "requires": { + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" + } + } + } + }, + "tailwindcss": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.2.7.tgz", + "integrity": "sha512-B6DLqJzc21x7wntlH/GsZwEXTBttVSl1FtCzC8WP4oBc/NKef7kaax5jeihkkCEWc831/5NDJ9gRNDK6NEioQQ==", + "dev": true, + "requires": { + "arg": "^5.0.2", + "chokidar": "^3.5.3", + "color-name": "^1.1.4", + "detective": "^5.2.1", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.2.12", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "lilconfig": "^2.0.6", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.0.9", + "postcss-import": "^14.1.0", + "postcss-js": "^4.0.0", + "postcss-load-config": "^3.1.4", + "postcss-nested": "6.0.0", + "postcss-selector-parser": "^6.0.11", + "postcss-value-parser": "^4.2.0", + "quick-lru": "^5.1.1", + "resolve": "^1.22.1" + }, + "dependencies": { + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + } + } + }, + "tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "peer": true + }, + "tar": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", + "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", + "dev": true, + "requires": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "dependencies": { + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dev": true, + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + }, + "dependencies": { + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + } + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + } + }, + "telejson": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/telejson/-/telejson-7.2.0.tgz", + "integrity": "sha512-1QTEcJkJEhc8OnStBx/ILRu5J2p0GjvWsBx56bmZRqnrkdBMUe+nX92jxV+p3dB4CP6PZCdJMQJwCggkNBMzkQ==", + "dev": true, + "requires": { + "memoizerific": "^1.11.3" + } + }, + "temp": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.4.tgz", + "integrity": "sha512-s0ZZzd0BzYv5tLSptZooSjK8oj6C+c19p7Vqta9+6NPOf7r+fxq0cJe6/oN4LTC79sy5NY8ucOJNgwsKCSbfqg==", + "dev": true, + "requires": { + "rimraf": "~2.6.2" + }, + "dependencies": { + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", "dev": true, "requires": { - "is-docker": "^2.0.0", - "is-wsl": "^2.1.1" + "glob": "^7.1.3" } } } }, - "tailwindcss": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.2.7.tgz", - "integrity": "sha512-B6DLqJzc21x7wntlH/GsZwEXTBttVSl1FtCzC8WP4oBc/NKef7kaax5jeihkkCEWc831/5NDJ9gRNDK6NEioQQ==", + "temp-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", + "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", + "dev": true + }, + "tempy": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tempy/-/tempy-1.0.1.tgz", + "integrity": "sha512-biM9brNqxSc04Ee71hzFbryD11nX7VPhQQY32AdDmjFvodsRFz/3ufeoTZ6uYkRFfGo188tENcASNs3vTdsM0w==", "dev": true, "requires": { - "arg": "^5.0.2", - "chokidar": "^3.5.3", - "color-name": "^1.1.4", - "detective": "^5.2.1", - "didyoumean": "^1.2.2", - "dlv": "^1.1.3", - "fast-glob": "^3.2.12", - "glob-parent": "^6.0.2", - "is-glob": "^4.0.3", - "lilconfig": "^2.0.6", - "micromatch": "^4.0.5", - "normalize-path": "^3.0.0", - "object-hash": "^3.0.0", - "picocolors": "^1.0.0", - "postcss": "^8.0.9", - "postcss-import": "^14.1.0", - "postcss-js": "^4.0.0", - "postcss-load-config": "^3.1.4", - "postcss-nested": "6.0.0", - "postcss-selector-parser": "^6.0.11", - "postcss-value-parser": "^4.2.0", - "quick-lru": "^5.1.1", - "resolve": "^1.22.1" + "del": "^6.0.0", + "is-stream": "^2.0.0", + "temp-dir": "^2.0.0", + "type-fest": "^0.16.0", + "unique-string": "^2.0.0" }, "dependencies": { - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "type-fest": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", + "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==", "dev": true } } }, - "tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "peer": true - }, "terser": { "version": "5.16.8", "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.8.tgz", @@ -19836,6 +35411,17 @@ } } }, + "test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "requires": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + } + }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -19858,11 +35444,71 @@ "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", "dev": true }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "tiny-emitter": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==" }, + "tiny-invariant": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.1.tgz", + "integrity": "sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==", + "dev": true + }, + "tinyspy": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.0.tgz", + "integrity": "sha512-d2eda04AN/cPOR89F7Xv5bK/jrQEhmcLFe6HFldoeO9AJtps+fqEnh486vnT/8y4bw38pSyxDcTCAq+Ks2aJTg==", + "dev": true + }, "tippy.js": { "version": "6.3.7", "resolved": "https://registry.npmjs.org/tippy.js/-/tippy.js-6.3.7.tgz", @@ -19880,6 +35526,12 @@ "rimraf": "^3.0.0" } }, + "tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true + }, "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -19894,12 +35546,24 @@ "is-number": "^7.0.0" } }, + "tocbot": { + "version": "4.25.0", + "resolved": "https://registry.npmjs.org/tocbot/-/tocbot-4.25.0.tgz", + "integrity": "sha512-kE5wyCQJ40hqUaRVkyQ4z5+4juzYsv/eK+aqD97N62YH0TxFhzJvo22RUQQZdO3YnXAk42ZOfOpjVdy+Z0YokA==", + "dev": true + }, "toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "dev": true }, + "token-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/token-stream/-/token-stream-1.0.0.tgz", + "integrity": "sha512-VSsyNPPW74RpHwR8Fc21uubwHY7wMDeJLys2IX5zJNih+OnAnaifKHo+1LHT7DAdloQ7apeaaWg8l7qnf/TnEg==", + "dev": true + }, "toposort": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", @@ -19926,6 +35590,18 @@ "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", "dev": true }, + "ts-dedent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz", + "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==", + "dev": true + }, + "ts-map": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ts-map/-/ts-map-1.0.3.tgz", + "integrity": "sha512-vDWbsl26LIcPGmDpoVzjEP6+hvHZkBkLW7JpvwbCv/5IYPJlsbzCVXY3wsCeAxAUeTclNOUZxnLdGh3VBD/J6w==", + "dev": true + }, "tsconfig-paths": { "version": "3.14.2", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", @@ -19982,6 +35658,12 @@ "prelude-ls": "^1.2.1" } }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + }, "type-fest": { "version": "0.21.3", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", @@ -20008,6 +35690,12 @@ "is-typed-array": "^1.1.9" } }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", + "dev": true + }, "typescript": { "version": "5.0.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", @@ -20020,11 +35708,18 @@ "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==" }, "ufo": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.1.1.tgz", - "integrity": "sha512-MvlCc4GHrmZdAllBc0iUDowff36Q9Ndw/UzqmEKyrfSzokTd9ZCy1i+IIk5hrYKkjoYVQyNbrw7/F8XJ2rEwTg==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.3.2.tgz", + "integrity": "sha512-o+ORpgGwaYQXgqGDwd+hkS4PuZ3QnmqMMxRuajK/a38L6fTpcE5GPIfrf+L/KemFzfUpeUQc1rRS1iDBozvnFA==", "dev": true }, + "uglify-js": { + "version": "3.17.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", + "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", + "dev": true, + "optional": true + }, "unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", @@ -20036,6 +35731,40 @@ "which-boxed-primitive": "^1.0.2" } }, + "undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "dev": true + }, + "unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dev": true, + "requires": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + } + }, + "unicode-match-property-value-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", + "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", + "dev": true + }, + "unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "dev": true + }, "unimport": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/unimport/-/unimport-3.0.4.tgz", @@ -20063,6 +35792,42 @@ } } }, + "unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "dev": true, + "requires": { + "crypto-random-string": "^2.0.0" + } + }, + "unist-util-is": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.1.0.tgz", + "integrity": "sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg==", + "dev": true + }, + "unist-util-visit": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz", + "integrity": "sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==", + "dev": true, + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + } + }, + "unist-util-visit-parents": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz", + "integrity": "sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==", + "dev": true, + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" + } + }, "universal-user-agent": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", @@ -20090,6 +35855,12 @@ } } }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "dev": true + }, "unplugin": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.3.1.tgz", @@ -20190,9 +35961,9 @@ "dev": true }, "update-browserslist-db": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", - "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", "requires": { "escalade": "^3.1.1", "picocolors": "^1.0.0" @@ -20211,11 +35982,58 @@ "resolved": "https://registry.npmjs.org/url-search-params-polyfill/-/url-search-params-polyfill-7.0.1.tgz", "integrity": "sha512-bAw7L2E+jn9XHG5P9zrPnHdO0yJub4U+yXJOdpcpkr7OBd9T8oll4lUos0iSGRcDvfZoLUKfx9a6aNmIhJ4+mQ==" }, + "use-callback-ref": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.1.tgz", + "integrity": "sha512-Lg4Vx1XZQauB42Hw3kK7JM6yjVjgFmFC5/Ab797s79aARomD2nEErc4mCgM8EZrARLmmbWpi5DGCadmK50DcAQ==", + "dev": true, + "requires": { + "tslib": "^2.0.0" + } + }, + "use-resize-observer": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/use-resize-observer/-/use-resize-observer-9.1.0.tgz", + "integrity": "sha512-R25VqO9Wb3asSD4eqtcxk8sJalvIOYBqS8MNZlpDSQ4l4xMQxC/J7Id9HoTqPq8FwULIn0PVW+OAqF2dyYbjow==", + "dev": true, + "requires": { + "@juggle/resize-observer": "^3.3.1" + } + }, + "use-sidecar": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.2.tgz", + "integrity": "sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw==", + "dev": true, + "requires": { + "detect-node-es": "^1.1.0", + "tslib": "^2.0.0" + } + }, + "util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "dev": true + }, "uuid": { "version": "8.3.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.0.tgz", @@ -20230,6 +36048,16 @@ "mitt": "^3.0.0" } }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -20258,6 +36086,12 @@ "rollup": "^3.25.2" } }, + "void-elements": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", + "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==", + "dev": true + }, "vue": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/vue/-/vue-3.3.1.tgz", @@ -20278,6 +36112,39 @@ "sanitize-html": "^2.0.0" } }, + "vue-component-type-helpers": { + "version": "1.8.27", + "resolved": "https://registry.npmjs.org/vue-component-type-helpers/-/vue-component-type-helpers-1.8.27.tgz", + "integrity": "sha512-0vOfAtI67UjeO1G6UiX5Kd76CqaQ67wrRZiOe7UAb9Jm6GzlUr/fC7CV90XfwapJRjpCMaZFhv1V0ajWRmE9Dg==", + "dev": true + }, + "vue-docgen-api": { + "version": "4.75.1", + "resolved": "https://registry.npmjs.org/vue-docgen-api/-/vue-docgen-api-4.75.1.tgz", + "integrity": "sha512-MECZ3uExz+ssmhD/2XrFoQQs93y17IVO1KDYTp8nr6i9GNrk67AAto6QAtilW1H/pTDPMkQxJ7w/25ZIqVtfAA==", + "dev": true, + "requires": { + "@babel/parser": "^7.21.4", + "@babel/types": "^7.21.4", + "@vue/compiler-dom": "^3.2.0", + "@vue/compiler-sfc": "^3.2.0", + "ast-types": "^0.16.1", + "hash-sum": "^2.0.0", + "lru-cache": "^8.0.3", + "pug": "^3.0.2", + "recast": "^0.23.1", + "ts-map": "^1.0.3", + "vue-inbrowser-compiler-independent-utils": "^4.69.0" + }, + "dependencies": { + "lru-cache": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-8.0.5.tgz", + "integrity": "sha512-MhWWlVnuab1RG5/zMRRcVGXZLCXrZTgfwMikgzCegsPnG62yDQo5JnqKkrK4jO5iKqDAZGItAqN5CtKBCBWRUA==", + "dev": true + } + } + }, "vue-draggable-next": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/vue-draggable-next/-/vue-draggable-next-2.2.1.tgz", @@ -20342,6 +36209,13 @@ } } }, + "vue-inbrowser-compiler-independent-utils": { + "version": "4.71.1", + "resolved": "https://registry.npmjs.org/vue-inbrowser-compiler-independent-utils/-/vue-inbrowser-compiler-independent-utils-4.71.1.tgz", + "integrity": "sha512-K3wt3iVmNGaFEOUR4JIThQRWfqokxLfnPslD41FDZB2ajXp789+wCqJyGYlIFsvEQ2P61PInw6/ph5iiqg51gg==", + "dev": true, + "requires": {} + }, "vue-json-pretty": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/vue-json-pretty/-/vue-json-pretty-2.2.4.tgz", @@ -20487,16 +36361,33 @@ } } }, + "walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "requires": { + "makeerror": "1.0.12" + } + }, "watchpack": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", - "peer": true, "requires": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" } }, + "wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dev": true, + "requires": { + "defaults": "^1.0.3" + } + }, "webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", @@ -20621,11 +36512,29 @@ "is-typed-array": "^1.1.10" } }, + "with": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/with/-/with-7.0.2.tgz", + "integrity": "sha512-RNGKj82nUPg3g5ygxkQl0R937xLyho1J24ItRCBTr/m1YnZkzJy1hUiHUJrc/VlsDQzsCnInEGSg3bci0Lmd4w==", + "dev": true, + "requires": { + "@babel/parser": "^7.9.6", + "@babel/types": "^7.9.6", + "assert-never": "^1.2.1", + "babel-walk": "3.0.0-canary-5" + } + }, "word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==" }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "dev": true + }, "wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -20663,11 +36572,58 @@ } } }, + "wrap-ansi-cjs": { + "version": "npm:wrap-ansi@7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + } + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, + "write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + } + }, "ws": { "version": "8.11.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index 37579dc950..56f5337bb0 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -16,7 +16,10 @@ "test:e2e:run": "npx cypress run --headed --browser chrome", "test:e2e:staging:open": "npx cypress open --config-file cypress.staging.config.js", "test:e2e:staging:run": "npx cypress run --config-file cypress.staging.config.js", - "tailwind:view": "tailwind-config-viewer -o" + "docs:tailwind": "tailwind-config-viewer -o", + "docs:storybook": "storybook dev -p 6006", + "docs:storybook:build": "storybook build", + "docs": "npm run docs:tailwind & npm run docs:storybook" }, "dependencies": { "@cubejs-client/core": "^0.31.63", @@ -27,9 +30,9 @@ "@octokit/core": "^3.6.0", "@tiptap/extension-link": "^2.1.12", "@tiptap/extension-placeholder": "^2.1.12", + "@tiptap/pm": "^2.1.12", "@tiptap/starter-kit": "^2.1.12", "@tiptap/vue-3": "^2.1.12", - "@tiptap/pm": "^2.1.12", "@vitejs/plugin-vue": "^4.2.3", "@vue/eslint-config-airbnb": "^7.0.0", "@vuelidate/core": "^2.0.1", @@ -73,7 +76,15 @@ "yup": "^0.32.11" }, "devDependencies": { + "@storybook/addon-essentials": "^7.6.10", + "@storybook/addon-interactions": "^7.6.10", + "@storybook/addon-links": "^7.6.10", + "@storybook/blocks": "^7.6.10", + "@storybook/test": "^7.6.10", + "@storybook/vue3": "^7.6.10", + "@storybook/vue3-vite": "^7.6.10", "@tailwindcss/line-clamp": "^0.4.2", + "@types/pluralize": "^0.0.33", "@typescript-eslint/eslint-plugin": "^5.4.0", "@typescript-eslint/parser": "^5.4.0", "@vue/compiler-sfc": "^3.2.29", @@ -86,11 +97,15 @@ "dotenv": "^16.0.3", "eslint": "^8.36.0", "eslint-plugin-cypress": "^2.12.1", + "eslint-plugin-storybook": "^0.6.15", "eslint-plugin-vue": "^9.10.0", "mini-css-extract-plugin": "^2.7.5", "postcss": "^8.4.21", + "react": "^18.2.0", + "react-dom": "^18.2.0", "rollup-plugin-visualizer": "^5.9.2", "sass": "^1.60.0", + "storybook": "^7.6.10", "tailwind-config-viewer": "^1.7.2", "tailwindcss": "^3.2.7", "terser-webpack-plugin": "^5.3.7", diff --git a/frontend/public/icons/crowd-icons.svg b/frontend/public/icons/crowd-icons.svg index 97772da7cc..abb5052f85 100644 --- a/frontend/public/icons/crowd-icons.svg +++ b/frontend/public/icons/crowd-icons.svg @@ -102,6 +102,17 @@ + + + + + + + + + + + @@ -127,6 +138,12 @@ + + + + + + diff --git a/frontend/scripts/docker-entrypoint.sh b/frontend/scripts/docker-entrypoint.sh index 6caa79975c..a9d3d4498c 100755 --- a/frontend/scripts/docker-entrypoint.sh +++ b/frontend/scripts/docker-entrypoint.sh @@ -32,6 +32,10 @@ declare -a ENV_VARIABLES=( "VUE_APP_IS_GIT_ENABLED" "VUE_APP_IS_GROUPSIO_ENABLED" "VUE_APP_IS_TWITTER_ENABLED" + "VUE_APP_STRIPE_SCALE_MONTHLY_PLAN_PAYMENT_LINK" + "VUE_APP_STRIPE_SCALE_YEARLY_PLAN_PAYMENT_LINK" + "VUE_APP_STRIPE_ESSENTIAL_MONTHLY_PLAN_PAYMENT_LINK" + "VUE_APP_STRIPE_ESSENTIAL_YEARLY_PLAN_PAYMENT_LINK" ) for ENV_VAR in "${ENV_VARIABLES[@]}" @@ -44,4 +48,4 @@ do done echo "Starting Nginx!" -nginx -g "daemon off;" \ No newline at end of file +nginx -g "daemon off;" diff --git a/frontend/src/assets/scss/buttons.scss b/frontend/src/assets/scss/buttons.scss index 48dcf7205d..2aa77d2d7f 100644 --- a/frontend/src/assets/scss/buttons.scss +++ b/frontend/src/assets/scss/buttons.scss @@ -310,59 +310,6 @@ @apply -mr-0.5; } -// Identities -.btn { - &--twitter, - &--twitter:hover { - @apply bg-white border border-gray-200; - } - - &--discord, - &--discord:hover { - background-color: rgba(88, 101, 242, 0.15); - } - - &--crunchbase, - &--crunchbase:hover { - background: rgba(20, 106, 255, 0.15); - } - - &--hackernews, - &--hackernews:hover { - background-color: rgba(255, 102, 0, 0.15); - color: #ff6600; - } - - &--email, - &--email:hover, - &--phone, - &--phone:hover, - &--custom-platform, - &--custom-platform:hover, - &--facebook, - &--facebook:hover { - @apply leading-none cursor-pointer bg-white text-gray-600 border border-gray-200; - } - - &--github, - &--github:hover, - &--devto, - &--devto:hover { - @apply bg-gray-100 border border-gray-200; - } - - &--slack, - &--slack:hover, - &--linkedin, - &--linkedin:hover, - &--stackoverflow, - &--stackoverflow:hover, - &--git, - &--git:hover { - @apply bg-white border border-gray-200; - } -} - .el-button { --el-button-outline-color: transparent !important; } diff --git a/frontend/src/assets/scss/helpers/_mixins.scss b/frontend/src/assets/scss/helpers/_mixins.scss new file mode 100755 index 0000000000..08a0ac5e8f --- /dev/null +++ b/frontend/src/assets/scss/helpers/_mixins.scss @@ -0,0 +1,8 @@ +/* ---------------------------------- *\ + Mixins & helpers +\* ---------------------------------- */ + +/* responsive font-size */ +@function rem($size) { + @return calc($size / 16) * 1rem; +} diff --git a/frontend/src/assets/scss/helpers/index.scss b/frontend/src/assets/scss/helpers/index.scss new file mode 100644 index 0000000000..9251548a6d --- /dev/null +++ b/frontend/src/assets/scss/helpers/index.scss @@ -0,0 +1 @@ +@import "mixins"; diff --git a/frontend/src/assets/scss/index.scss b/frontend/src/assets/scss/index.scss index 0065a45326..b6af583727 100644 --- a/frontend/src/assets/scss/index.scss +++ b/frontend/src/assets/scss/index.scss @@ -4,6 +4,7 @@ @tailwind utilities; /* You can add global styles to this file, and also import other style files */ +@import 'helpers'; @import 'layout'; @import 'typography'; @import 'filter'; @@ -31,3 +32,6 @@ @import 'form/input'; @import 'form/checkbox'; @import 'form/switch'; + +@import '../../../config/styles'; +@import '../../shared/ui-kit'; diff --git a/frontend/src/config.js b/frontend/src/config.js index f623658de2..15e621e810 100644 --- a/frontend/src/config.js +++ b/frontend/src/config.js @@ -51,6 +51,14 @@ const defaultConfig = { .VUE_APP_STRIPE_EAGLE_EYE_PLAN_PAYMENT_LINK || '', customerPortalLink: import.meta.env.VUE_APP_STRIPE_CUSTOMER_PORTAL_LINK || '', + scaleMonthlyPaymentLink: + import.meta.env.VUE_APP_STRIPE_SCALE_MONTHLY_PLAN_PAYMENT_LINK || '', + scaleYearlyPaymentLink: + import.meta.env.VUE_APP_STRIPE_SCALE_YEARLY_PLAN_PAYMENT_LINK || '', + essentialMonthlyPaymentLink: + import.meta.env.VUE_APP_STRIPE_ESSENTIAL_MONTHLY_PLAN_PAYMENT_LINK || '', + essentialYearlyPaymentLink: + import.meta.env.VUE_APP_STRIPE_ESSENTIAL_YEARLY_PLAN_PAYMENT_LINK || '', }, sampleTenant: { id: import.meta.env.VUE_APP_SAMPLE_TENANT_ID, @@ -102,6 +110,14 @@ const composedConfig = { || '', customerPortalLink: 'CROWD_VUE_APP_STRIPE_CUSTOMER_PORTAL_LINK' || '', + scaleMonthlyPaymentLink: + 'CROWD_VUE_APP_STRIPE_SCALE_MONTHLY_PLAN_PAYMENT_LINK' || '', + scaleYearlyPaymentLink: + 'CROWD_VUE_APP_STRIPE_SCALE_YEARLY_PLAN_PAYMENT_LINK' || '', + essentialMonthlyPaymentLink: + 'CROWD_VUE_APP_STRIPE_ESSENTIAL_MONTHLY_PLAN_PAYMENT_LINK' || '', + essentialYearlyPaymentLink: + 'CROWD_VUE_APP_STRIPE_ESSENTIAL_YEARLY_PLAN_PAYMENT_LINK' || '', }, sampleTenant: { id: 'CROWD_VUE_APP_SAMPLE_TENANT_ID', diff --git a/frontend/src/i18n/en.js b/frontend/src/i18n/en.js index cca01dcbe2..f89874842e 100644 --- a/frontend/src/i18n/en.js +++ b/frontend/src/i18n/en.js @@ -458,7 +458,8 @@ const en = { Members: { count: '[Contacts] Count', cumulativeCount: '[Contacts] Cumulative Count', - score: '[Contacts] Engagement Level', + score: '[Contacts] Engagement Level Score', + engagementLevel: '[Contacts] Engagement Level', location: '[Contacts] Location', organization: '[Contacts] Organization', joinedAt: '[Contacts] Joined Date', diff --git a/frontend/src/integrations/github/components/github-connect.vue b/frontend/src/integrations/github/components/github-connect.vue index 40a7b6b4e2..c71cad0d08 100644 --- a/frontend/src/integrations/github/components/github-connect.vue +++ b/frontend/src/integrations/github/components/github-connect.vue @@ -8,7 +8,6 @@ import config from '@/config'; import ConfirmDialog from '@/shared/dialog/confirm-dialog'; import { useRoute, useRouter } from 'vue-router'; -const emit = defineEmits(['inviteColleagues']); defineProps({ integration: { type: Object, @@ -29,28 +28,26 @@ const connect = () => { 'Are you the admin of your GitHub organization?', titleClass: 'text-lg pt-2', message: - `Only GitHub users with admin permissions are able to connect crowd.dev's GitHub integration. - If you are an organization contact, you will need an approval from the GitHub workspace admin. Read more`, + route.name !== 'onboard' ? `Only GitHub users with admin permissions are able to connect crowd.dev's GitHub integration. + If you are an organization contact, you will need an approval from the GitHub workspace admin. Read more` + : 'Only GitHub users with admin permissions are able to connect crowd.dev\'s GitHub integration. You can request admin permissions or connect GitHub later by inviting your organization\'s admin to the workspace. Read more', icon: 'ri-information-line', confirmButtonText: 'I\'m the GitHub organization admin', cancelButtonText: 'Invite organization admin to this workspace', - verticalCancelButtonClass: 'btn btn--md btn--bordererd w-full', + verticalCancelButtonClass: 'btn btn--md bg-white hover:bg-gray-100 shadow border border-gray-50 w-full hover:text-gray-600 hover:border-gray-100', verticalConfirmButtonClass: 'btn btn--md btn--primary w-full !mb-2', vertical: true, distinguishCancelAndClose: true, autofocus: false, messageClass: 'text-xs !leading-5 !mt-1 text-gray-600', + showCancelButton: route.name !== 'onboard', }).then(() => { window.open(githubConnectUrl.value, '_self'); }).catch((action) => { if (action === 'cancel') { - if (route.name === 'onboard') { - emit('inviteColleagues'); - } else { - router.push({ - name: 'settings', - }); - } + router.push({ + name: 'settings', + }); } }); }; diff --git a/frontend/src/integrations/integrations-config.js b/frontend/src/integrations/integrations-config.js index 468a4e31a7..f5cdde2cd9 100644 --- a/frontend/src/integrations/integrations-config.js +++ b/frontend/src/integrations/integrations-config.js @@ -16,6 +16,7 @@ import git from './git'; import facebook from './facebook'; import n8n from './n8n'; import groupsio from './groupsio'; +import youtube from './youtube'; import salesforce from './salesforce'; import segment from './segment'; import census from './census'; @@ -43,6 +44,7 @@ class IntegrationsConfig { groupsio, // make, facebook, + youtube, salesforce, segment, census, diff --git a/frontend/src/integrations/twitter/components/twitter-connect.vue b/frontend/src/integrations/twitter/components/twitter-connect.vue index d678ca2307..66c7653882 100644 --- a/frontend/src/integrations/twitter/components/twitter-connect.vue +++ b/frontend/src/integrations/twitter/components/twitter-connect.vue @@ -7,8 +7,6 @@ /> @@ -48,9 +46,7 @@ onMounted(() => { }); onMounted(async () => { - isTwitterEnabled.value = FeatureFlag.isFlagEnabled( - FeatureFlag.flags.twitter, - ); + isTwitterEnabled.value = FeatureFlag.isFlagEnabled(FeatureFlag.flags.twitter); }); // Only render twitter drawer and settings button, if integration has settings @@ -81,10 +77,10 @@ const upgradePlan = () => { router.push('/settings?activeTab=plans'); }; -const settings = () => { - drawerVisible.value = true; -}; - +// const settings = () => { +// drawerVisible.value = true; +// }; +// Youtube Logo + + + + + + + + + diff --git a/frontend/src/integrations/youtube/components/youtube-connect.vue b/frontend/src/integrations/youtube/components/youtube-connect.vue new file mode 100644 index 0000000000..2787b14505 --- /dev/null +++ b/frontend/src/integrations/youtube/components/youtube-connect.vue @@ -0,0 +1,31 @@ + + + + + diff --git a/frontend/src/integrations/youtube/config.js b/frontend/src/integrations/youtube/config.js new file mode 100644 index 0000000000..b36f9e6fcc --- /dev/null +++ b/frontend/src/integrations/youtube/config.js @@ -0,0 +1,26 @@ +import YoutubeConnect from './components/youtube-connect.vue'; + +export default { + enabled: true, + name: 'Youtube', + backgroundColor: '#FFFFFF', + borderColor: '#FFFFFF', + description: + 'Connect Youtube to sync comments based on channels or selected keywords.', + image: + 'https://cdn-icons-png.flaticon.com/512/174/174883.png', + connectComponent: YoutubeConnect, + url: (username) => `https://www.youtube.com/channel/${username}`, + chartColor: '#FF9845', + showProfileLink: true, + activityDisplay: { + showLinkToUrl: true, + }, + conversationDisplay: { + replyContent: (conversation) => ({ + icon: 'ri-reply-line', + copy: 'reply', + number: conversation.activityCount - 1, + }), + }, +}; diff --git a/frontend/src/integrations/youtube/index.js b/frontend/src/integrations/youtube/index.js new file mode 100644 index 0000000000..e81a18f3ed --- /dev/null +++ b/frontend/src/integrations/youtube/index.js @@ -0,0 +1,3 @@ +import config from './config'; + +export default config; diff --git a/frontend/src/middleware/auth/auth-guard.js b/frontend/src/middleware/auth/auth-guard.js index a08bfb6bd8..4c9a810921 100644 --- a/frontend/src/middleware/auth/auth-guard.js +++ b/frontend/src/middleware/auth/auth-guard.js @@ -1,6 +1,7 @@ import { PermissionChecker } from '@/modules/user/permission-checker'; import config from '@/config'; import { tenantSubdomain } from '@/modules/tenant/tenant-subdomain'; +import { isTrialExpired } from '@/utils/date'; function isGoingToIntegrationsPage(to) { return to.name === 'integration'; @@ -50,6 +51,19 @@ export default async function ({ return; } + if (!currentUser.acceptedTermsAndPrivacy) { + router.push({ path: '/auth/terms-and-privacy' }); + return; + } + + if (store.getters['auth/currentTenant'] && isTrialExpired(store.getters['auth/currentTenant'])) { + if (!window.location.href.includes('/onboard/plans') + && !window.location.href.includes('/onboard/payment')) { + window.location.href = `${config.frontendUrl.protocol}://${config.frontendUrl.host}/onboard/plans`; + } + return; + } + // Temporary fix if ( to.meta.permission @@ -62,11 +76,6 @@ export default async function ({ return; } - if (!currentUser.acceptedTermsAndPrivacy) { - router.push({ path: '/auth/terms-and-privacy' }); - return; - } - if ( ['multi', 'multi-with-subdomain'].includes( config.tenantMode, diff --git a/frontend/src/modules/activity/activity-service.js b/frontend/src/modules/activity/activity-service.js index 50b2c03ec5..07ae3e9a51 100644 --- a/frontend/src/modules/activity/activity-service.js +++ b/frontend/src/modules/activity/activity-service.js @@ -1,5 +1,7 @@ import authAxios from '@/shared/axios/auth-axios'; import AuthCurrentTenant from '@/modules/auth/auth-current-tenant'; +import { store } from '@/store'; +import moment from 'moment'; export class ActivityService { static async update(id, data) { @@ -20,12 +22,9 @@ export class ActivityService { const tenantId = AuthCurrentTenant.get(); - const response = await authAxios.delete( - `/tenant/${tenantId}/activity`, - { - params, - }, - ); + const response = await authAxios.delete(`/tenant/${tenantId}/activity`, { + params, + }); return response.data; } @@ -41,17 +40,21 @@ export class ActivityService { return response.data; } - static async query( - body, - ) { + static async query(body, countOnly = false) { const sampleTenant = AuthCurrentTenant.getSampleTenantData(); const tenantId = sampleTenant?.id || AuthCurrentTenant.get(); + const currentTenant = store.getters['auth/currentTenant']; + + const isTenantNew = moment(currentTenant.createdAt).add(1, 'months').isAfter(moment()); + // If tenant is less than a month old, use old query + // Else use new query const response = await authAxios.post( `/tenant/${tenantId}/activity/query`, - body, + { ...body, countOnly }, { headers: { + ...(isTenantNew ? {} : { 'x-crowd-api-version': '1' }), Authorization: sampleTenant?.token, }, }, @@ -64,14 +67,11 @@ export class ActivityService { const sampleTenant = AuthCurrentTenant.getSampleTenantData(); const tenantId = sampleTenant?.id || AuthCurrentTenant.get(); - const response = await authAxios.get( - `/tenant/${tenantId}/activity/type`, - { - headers: { - Authorization: sampleTenant?.token, - }, + const response = await authAxios.get(`/tenant/${tenantId}/activity/type`, { + headers: { + Authorization: sampleTenant?.token, }, - ); + }); return response.data; } diff --git a/frontend/src/modules/activity/components/activity-timeline.vue b/frontend/src/modules/activity/components/activity-timeline.vue index 80d88abc85..ce2390f19c 100644 --- a/frontend/src/modules/activity/components/activity-timeline.vue +++ b/frontend/src/modules/activity/components/activity-timeline.vue @@ -192,14 +192,13 @@ import { import debounce from 'lodash/debounce'; import AppActivityContent from '@/modules/activity/components/activity-content.vue'; import { onSelectMouseLeave } from '@/utils/select'; -import authAxios from '@/shared/axios/auth-axios'; import { CrowdIntegrations } from '@/integrations/integrations-config'; import AppMemberDisplayName from '@/modules/member/components/member-display-name.vue'; import AppActivityLink from '@/modules/activity/components/activity-link.vue'; -import AuthCurrentTenant from '@/modules/auth/auth-current-tenant'; import AppActivityContentFooter from '@/modules/activity/components/activity-content-footer.vue'; import AppActivityHeader from '@/modules/activity/components/activity-header.vue'; import AppActivityDropdown from '@/modules/activity/components/activity-dropdown.vue'; +import { ActivityService } from '../activity-service'; const SearchIcon = h( 'i', // type @@ -245,13 +244,13 @@ const fetchActivities = async (reload = false) => { } const filterToApply = { - platform: platform.value ?? undefined, + platform: platform.value ? { eq: platform.value } : undefined, }; if (props.entityType === 'member') { - filterToApply.memberId = props.entityId; + filterToApply.memberId = { in: [props.entityId] }; } else { - filterToApply[`${props.entityType}s`] = [props.entityId]; + filterToApply.organizationId = { in: [props.entityId] }; } if (props.entityId) { @@ -303,24 +302,12 @@ const fetchActivities = async (reload = false) => { loading.value = true; - const sampleTenant = AuthCurrentTenant.getSampleTenantData(); - const tenantId = sampleTenant?.id - || store.getters['auth/currentTenant'].id; - - const { data } = await authAxios.post( - `/tenant/${tenantId}/activity/query`, - { - filter: filterToApply, - orderBy: 'timestamp_DESC', - limit: limit.value, - offset: offset.value, - }, - { - headers: { - Authorization: sampleTenant?.token, - }, - }, - ); + const data = await ActivityService.query({ + filter: filterToApply, + orderBy: 'timestamp_DESC', + limit: limit.value, + offset: offset.value, + }); filter = { ...filterToApply }; loading.value = false; diff --git a/frontend/src/modules/activity/config/filters/member/config.ts b/frontend/src/modules/activity/config/filters/member/config.ts index 210c79c074..e7fa19cf49 100644 --- a/frontend/src/modules/activity/config/filters/member/config.ts +++ b/frontend/src/modules/activity/config/filters/member/config.ts @@ -41,7 +41,7 @@ const member: MultiSelectAsyncFilterConfig = { }, apiFilterRenderer({ value, include }: MultiSelectAsyncFilterValue): any[] { const filter = { - memberId: value, + memberId: { in: value }, }; return [ (include ? filter : { not: filter }), diff --git a/frontend/src/modules/activity/config/filters/organizations/config.ts b/frontend/src/modules/activity/config/filters/organizations/config.ts index 6e60f1a9ea..c7e917f7a4 100644 --- a/frontend/src/modules/activity/config/filters/organizations/config.ts +++ b/frontend/src/modules/activity/config/filters/organizations/config.ts @@ -19,7 +19,7 @@ const organizations: MultiSelectAsyncFilterConfig = { value: organization.id, logo: organization.logo, }))), - remotePopulateItems: (ids: string[]) => OrganizationService.listAutocomplete({ + remotePopulateItems: (ids: string[]) => OrganizationService.query({ filter: { and: [ ...DEFAULT_ORGANIZATION_FILTERS, @@ -28,7 +28,7 @@ const organizations: MultiSelectAsyncFilterConfig = { }, ], }, - orderBy: null, + orderBy: 'displayName_ASC', limit: ids.length, offset: 0, }) @@ -43,7 +43,7 @@ const organizations: MultiSelectAsyncFilterConfig = { }, apiFilterRenderer({ value, include }: MultiSelectAsyncFilterValue): any[] { const filter = { - organizationId: value, + organizationId: { in: value }, }; return [ (include ? filter : { not: filter }), diff --git a/frontend/src/modules/activity/config/filters/platform/config.ts b/frontend/src/modules/activity/config/filters/platform/config.ts index 5273a936bd..930cab8b21 100644 --- a/frontend/src/modules/activity/config/filters/platform/config.ts +++ b/frontend/src/modules/activity/config/filters/platform/config.ts @@ -33,8 +33,9 @@ const platform: MultiSelectFilterConfig = { }, apiFilterRenderer({ value, include }: MultiSelectFilterValue): any[] { const filter = { - or: value.map((p) => ({ platform: p })), + platform: { in: value }, }; + return [ (include ? filter : { not: filter }), ]; diff --git a/frontend/src/modules/activity/config/filters/sentiment/config.ts b/frontend/src/modules/activity/config/filters/sentiment/config.ts index 93379a7a1d..c49ca374e7 100644 --- a/frontend/src/modules/activity/config/filters/sentiment/config.ts +++ b/frontend/src/modules/activity/config/filters/sentiment/config.ts @@ -20,11 +20,7 @@ const sentiment: MultiSelectFilterConfig = { }, apiFilterRenderer({ value, include }: MultiSelectFilterValue): any[] { const filter = { - or: [ - ...(value.includes('positive') ? [{ sentiment: { gte: 67 } }] : []), - ...(value.includes('negative') ? [{ sentiment: { lt: 33 } }] : []), - ...(value.includes('neutral') ? [{ sentiment: { between: [33, 67] } }] : []), - ], + sentiment: { in: value }, }; return [ (include ? filter : { not: filter }), diff --git a/frontend/src/modules/activity/store/constants.js b/frontend/src/modules/activity/store/constants.js index 1b7bc79eaa..91bd66efbe 100644 --- a/frontend/src/modules/activity/store/constants.js +++ b/frontend/src/modules/activity/store/constants.js @@ -6,5 +6,8 @@ export const DEFAULT_ACTIVITY_FILTERS = { isBot: { not: true, }, + isDeleted: { + not: true, + }, }, }; diff --git a/frontend/src/modules/auth/auth-service.js b/frontend/src/modules/auth/auth-service.js index 6a7e86ac3a..6f3cb6ee82 100644 --- a/frontend/src/modules/auth/auth-service.js +++ b/frontend/src/modules/auth/auth-service.js @@ -156,4 +156,13 @@ export class AuthService { return Boolean(urlParams.get('social')); } + + static confirmPayment(sessionId) { + const tenantId = AuthCurrentTenant.get(); + return authAxios + .post(`/tenant/${tenantId}/payment/confirm`, { + sessionId, + }) + .then((response) => response.data); + } } diff --git a/frontend/src/modules/auth/auth-socket.js b/frontend/src/modules/auth/auth-socket.js index 2fd54e7553..b23bf292da 100644 --- a/frontend/src/modules/auth/auth-socket.js +++ b/frontend/src/modules/auth/auth-socket.js @@ -1,5 +1,5 @@ import io from 'socket.io-client'; -import { computed } from 'vue'; +import { computed, h } from 'vue'; import pluralize from 'pluralize'; import config from '@/config'; import { store } from '@/store'; @@ -9,9 +9,20 @@ import { getEnrichmentMax, } from '@/modules/member/member-enrichment'; import { useMemberStore } from '@/modules/member/store/pinia'; +import { router } from '@/router'; +import { useOrganizationStore } from '@/modules/organization/store/pinia'; let socketIoClient; +const SocketEvents = { + connect: 'connect', + disconnect: 'disconnect', + integrationCompleted: 'integration-completed', + tenantPlanUpgraded: 'tenant-plan-upgraded', + bulkEnrichment: 'bulk-enrichment', + orgMerge: 'org-merge', +}; + export const connectSocket = (token) => { if (socketIoClient && socketIoClient.connected) { socketIoClient.disconnect(); @@ -36,15 +47,15 @@ export const connectSocket = (token) => { forceNew: true, }); - socketIoClient.on('connect', () => { + socketIoClient.on(SocketEvents.connect, () => { console.info('Socket connected'); }); - socketIoClient.on('disconnect', () => { + socketIoClient.on(SocketEvents.disconnect, () => { console.info('Socket disconnected'); }); - socketIoClient.on('integration-completed', (data) => { + socketIoClient.on(SocketEvents.integrationCompleted, (data) => { console.info('Integration onboarding done', data); store.dispatch( 'integration/doFind', @@ -53,7 +64,7 @@ export const connectSocket = (token) => { }); socketIoClient.on( - 'tenant-plan-upgraded', + SocketEvents.tenantPlanUpgraded, async (data) => { console.info( 'Tenant plan is upgraded. Force a hard refresh!', @@ -72,7 +83,7 @@ export const connectSocket = (token) => { }, ); - socketIoClient.on('bulk-enrichment', async (data) => { + socketIoClient.on(SocketEvents.bulkEnrichment, async (data) => { let parsed = data; if (typeof data === 'string') { parsed = JSON.parse(parsed); @@ -116,6 +127,74 @@ export const connectSocket = (token) => { } } }); + + socketIoClient.on(SocketEvents.orgMerge, (payload) => { + const { + success, + tenantId, + userId, + primaryOrgId, + secondaryOrgId, + original, + toMerge, + } = JSON.parse(payload); + + if (currentTenant.value.id !== tenantId && currentUser.value.id !== userId) { + return; + } + + const { mergedOrganizations, removeMergedOrganizations } = useOrganizationStore(); + + const buttonElement = h( + 'el-button', + { + class: 'btn btn--xs btn--bordered !h-6 !w-fit', + onClick: () => { + router.push({ + name: 'organizationView', + params: { id: primaryOrgId }, + }); + Message.closeAll(); + }, + }, + 'View organization', + ); + + const messageElements = [buttonElement]; + + if (original && toMerge) { + const descriptionElement = h( + 'span', + { + innerHTML: `${toMerge} merged with ${original}.`, + }, + ); + + removeMergedOrganizations(primaryOrgId); + + messageElements.unshift(descriptionElement); + } + + Message.closeAll(); + + if (success) { + Message.success( + h( + 'div', + { + class: 'flex flex-col gap-2', + }, + messageElements, + ), + { + title: + 'Organizations merged successfully', + }, + ); + } else { + Message.error(`There was an error merging ${toMerge} with ${original}`); + } + }); }; export const disconnectSocket = () => { diff --git a/frontend/src/modules/auth/store/actions.js b/frontend/src/modules/auth/store/actions.js index 724f29a9f5..893bb25115 100644 --- a/frontend/src/modules/auth/store/actions.js +++ b/frontend/src/modules/auth/store/actions.js @@ -13,6 +13,8 @@ import { connectSocket, disconnectSocket, } from '@/modules/auth/auth-socket'; +import config from '@/config'; +import { isTrialExpired } from '@/utils/date'; export default { async doInit({ commit, dispatch, state }) { @@ -146,7 +148,6 @@ export default { }, async doSignout({ commit }) { - commit('AUTH_START'); AuthService.signout(); commit('AUTH_SUCCESS', { currentUser: null, @@ -227,7 +228,7 @@ export default { }) .then(() => { commit('EMAIL_VERIFY_SUCCESS'); - router.push('/'); + router.push('/onboard/plans'); }) .catch((error) => { Errors.handle(error); @@ -267,7 +268,11 @@ export default { await dispatch('doRefreshCurrentUser'); if (redirect) { - router.push('/'); + if (isTrialExpired(tenant)) { + router.push({ name: 'onboardPlans' }); + } else { + router.push('/'); + } } }, diff --git a/frontend/src/modules/auth/store/mutations.js b/frontend/src/modules/auth/store/mutations.js index 152d1ebe7a..495f8ab7f6 100644 --- a/frontend/src/modules/auth/store/mutations.js +++ b/frontend/src/modules/auth/store/mutations.js @@ -1,5 +1,7 @@ import formbricks, { setupFormbricks } from '@/plugins/formbricks'; import AuthCurrentTenant from '@/modules/auth/auth-current-tenant'; +import { isTrialExpired } from '@/utils/date'; +import config from '@/config'; export default { CURRENT_USER_REFRESH_SUCCESS(state, payload) { @@ -18,6 +20,14 @@ export default { state.currentTenant = AuthCurrentTenant.selectAndSaveOnStorageFor( payload.currentUser, ); + if (state.currentTenant && isTrialExpired(state.currentTenant)) { + if (!window.location.href.includes('/onboard/plans') + && !window.location.href.includes('/onboard/payment') + && !window.location.href.includes('/auth/verify-email')) { + window.location.href = `${config.frontendUrl.protocol}://${config.frontendUrl.host}/onboard/plans`; + } + return; + } state.loading = false; if (state.currentUser) { @@ -111,6 +121,14 @@ export default { state.currentTenant = AuthCurrentTenant.selectAndSaveOnStorageFor( payload.currentUser, ); + if (state.currentTenant && isTrialExpired(state.currentTenant)) { + if (!window.location.href.includes('/onboard/plans') + && !window.location.href.includes('/onboard/payment') + && !window.location.href.includes('/auth/verify-email')) { + window.location.href = `${config.frontendUrl.protocol}://${config.frontendUrl.host}/onboard/plans`; + } + return; + } if (state.currentUser) { // initialize Formbricks setupFormbricks(state.currentUser); diff --git a/frontend/src/modules/automation/config/automation-types/slack/slack-action.vue b/frontend/src/modules/automation/config/automation-types/slack/slack-action.vue index 7b77356d07..e07519de9a 100644 --- a/frontend/src/modules/automation/config/automation-types/slack/slack-action.vue +++ b/frontend/src/modules/automation/config/automation-types/slack/slack-action.vue @@ -13,8 +13,8 @@
- - App installed + + App installed
diff --git a/frontend/src/modules/conversation/components/conversation-details.vue b/frontend/src/modules/conversation/components/conversation-details.vue index 2d54608b04..4a2941b62c 100644 --- a/frontend/src/modules/conversation/components/conversation-details.vue +++ b/frontend/src/modules/conversation/components/conversation-details.vue @@ -289,10 +289,10 @@ export default { filter: { and: [ { - type: value, + type: { eq: value }, }, { - conversationId: this.conversation.id, + conversationId: { in: [this.conversation.id] }, }, ], }, diff --git a/frontend/src/modules/conversation/components/conversation-list.vue b/frontend/src/modules/conversation/components/conversation-list.vue index d1e4495994..3ccfc75335 100644 --- a/frontend/src/modules/conversation/components/conversation-list.vue +++ b/frontend/src/modules/conversation/components/conversation-list.vue @@ -32,9 +32,9 @@ :total="totalConversations" :current-page="pagination.page" :has-page-counter="false" + :sorter="false" module="conversation" position="top" - @change-sorter="doChangeFilter" /> @@ -89,9 +89,7 @@ const { fetchConversation } = conversationStore; const loading = ref(false); -const sorterFilter = computed(() => (filters.value.order.prop === 'activityCount' - ? 'trending' - : 'recentActivity')); +const sorterFilter = ref('recentActivity'); const emptyState = computed(() => ({ title: 'No conversations found', @@ -99,13 +97,6 @@ const emptyState = computed(() => ({ "We couldn't find any results that match your search criteria, please try a different query", })); -const doChangeFilter = (filter) => { - filters.value.order = { - prop: filter === 'recentActivity' ? 'lastActive' : 'activityCount', - order: 'descending', - }; -}; - const isLoadMoreVisible = computed(() => ( pagination.value.page * pagination.value.perPage diff --git a/frontend/src/modules/conversation/config/filters/lastActivityDate/config.ts b/frontend/src/modules/conversation/config/filters/lastActivityDate/config.ts index 6857fd3d4b..1db3dd634e 100644 --- a/frontend/src/modules/conversation/config/filters/lastActivityDate/config.ts +++ b/frontend/src/modules/conversation/config/filters/lastActivityDate/config.ts @@ -17,7 +17,18 @@ const lastActivityDate: DateFilterConfig = { return itemLabelRendererByType[FilterConfigType.DATE]('Last activity', value, options); }, apiFilterRenderer(value: DateFilterValue): any[] { - return apiFilterRendererByType[FilterConfigType.DATE]('lastActive', value); + let { operator } = value; + + if (value.operator === 'gt') { + operator = 'gte'; + } else if (value.operator === 'lt') { + operator = 'lte'; + } + + return apiFilterRendererByType[FilterConfigType.DATE]('lastActive', { + ...value, + operator, + }); }, }; diff --git a/frontend/src/modules/conversation/store/state.ts b/frontend/src/modules/conversation/store/state.ts index c1b4823f32..db9f79a503 100644 --- a/frontend/src/modules/conversation/store/state.ts +++ b/frontend/src/modules/conversation/store/state.ts @@ -17,7 +17,7 @@ export default () => ({ search: '', relation: 'and', order: { - prop: 'activityCount', + prop: 'lastActive', order: 'descending', }, lastActivityDate: { diff --git a/frontend/src/modules/dashboard/components/activity/dashboard-activity-sentiment.vue b/frontend/src/modules/dashboard/components/activity/dashboard-activity-sentiment.vue index f3e3d43ebf..6ae9a84321 100644 --- a/frontend/src/modules/dashboard/components/activity/dashboard-activity-sentiment.vue +++ b/frontend/src/modules/dashboard/components/activity/dashboard-activity-sentiment.vue @@ -1,191 +1,177 @@ - + + diff --git a/frontend/src/modules/dashboard/components/activity/dashboard-activity-types.vue b/frontend/src/modules/dashboard/components/activity/dashboard-activity-types.vue index 6813bc1c8c..af068e3b17 100644 --- a/frontend/src/modules/dashboard/components/activity/dashboard-activity-types.vue +++ b/frontend/src/modules/dashboard/components/activity/dashboard-activity-types.vue @@ -1,127 +1,91 @@ diff --git a/frontend/src/modules/dashboard/components/conversations/dashboard-conversation-list.vue b/frontend/src/modules/dashboard/components/conversations/dashboard-conversation-list.vue index 80f80a9df7..962b528d4e 100644 --- a/frontend/src/modules/dashboard/components/conversations/dashboard-conversation-list.vue +++ b/frontend/src/modules/dashboard/components/conversations/dashboard-conversation-list.vue @@ -5,7 +5,7 @@ v-for="(el, ci) of new Array(2)" :key="el" :class="{ - 'border-b': ci < trendingConversations.length - 1, + 'border-b': ci < recentConversations.length - 1, }" :loading="true" @conversation-destroyed="refreshConversations" @@ -13,10 +13,10 @@
@@ -76,7 +76,7 @@ export default { }, computed: { ...mapGetters('dashboard', [ - 'trendingConversations', + 'recentConversations', 'conversations', ]), allConversationsFilter() { @@ -84,7 +84,7 @@ export default { search: '', relation: 'and', order: { - prop: 'activityCount', + prop: 'lastActive', order: 'descending', }, lastActivityDate: { @@ -98,7 +98,7 @@ export default { methods: { refreshConversations() { this.$store.dispatch( - 'dashboard/getTrendingConversations', + 'dashboard/getRecentConversations', ); }, }, diff --git a/frontend/src/modules/dashboard/components/dashboard-activities.vue b/frontend/src/modules/dashboard/components/dashboard-activities.vue index fbba92a2c1..aa83628fc9 100644 --- a/frontend/src/modules/dashboard/components/dashboard-activities.vue +++ b/frontend/src/modules/dashboard/components/dashboard-activities.vue @@ -25,28 +25,26 @@ New activities
-
- Overall sentiment -
@@ -61,14 +59,14 @@
@@ -77,14 +75,8 @@
- + + diff --git a/frontend/src/modules/dashboard/components/dashboard-count.vue b/frontend/src/modules/dashboard/components/dashboard-count.vue index 42b46336a4..6734e45e23 100644 --- a/frontend/src/modules/dashboard/components/dashboard-count.vue +++ b/frontend/src/modules/dashboard/components/dashboard-count.vue @@ -1,181 +1,101 @@ - + + diff --git a/frontend/src/modules/dashboard/components/dashboard-members.vue b/frontend/src/modules/dashboard/components/dashboard-members.vue index 817adb99d9..b6a7becb5f 100644 --- a/frontend/src/modules/dashboard/components/dashboard-members.vue +++ b/frontend/src/modules/dashboard/components/dashboard-members.vue @@ -25,21 +25,22 @@ New contacts
@@ -116,7 +117,7 @@
- Active contacts + Active contacts
@@ -209,80 +211,50 @@ - + diff --git a/frontend/src/modules/dashboard/components/dashboard-organizations.vue b/frontend/src/modules/dashboard/components/dashboard-organizations.vue index 3961a99cb1..3da6f65ea9 100644 --- a/frontend/src/modules/dashboard/components/dashboard-organizations.vue +++ b/frontend/src/modules/dashboard/components/dashboard-organizations.vue @@ -24,21 +24,22 @@ New organizations
@@ -114,21 +115,22 @@
@@ -187,74 +189,47 @@ - + + diff --git a/frontend/src/modules/dashboard/components/dashboard-widget-chart.vue b/frontend/src/modules/dashboard/components/dashboard-widget-chart.vue index 5830021465..5525205f56 100644 --- a/frontend/src/modules/dashboard/components/dashboard-widget-chart.vue +++ b/frontend/src/modules/dashboard/components/dashboard-widget-chart.vue @@ -1,43 +1,36 @@ - - + + diff --git a/frontend/src/modules/member/components/form/member-form-emails.vue b/frontend/src/modules/member/components/form/member-form-emails.vue new file mode 100644 index 0000000000..7397cd1a01 --- /dev/null +++ b/frontend/src/modules/member/components/form/member-form-emails.vue @@ -0,0 +1,86 @@ + + + + + diff --git a/frontend/src/modules/member/components/form/member-form-identities.vue b/frontend/src/modules/member/components/form/member-form-identities.vue index c3a80ac1da..05153511d8 100644 --- a/frontend/src/modules/member/components/form/member-form-identities.vue +++ b/frontend/src/modules/member/components/form/member-form-identities.vue @@ -1,105 +1,53 @@ + + + + + + diff --git a/frontend/src/modules/member/components/member-display-name.vue b/frontend/src/modules/member/components/member-display-name.vue index c13caa6df8..0c385bf645 100644 --- a/frontend/src/modules/member/components/member-display-name.vue +++ b/frontend/src/modules/member/components/member-display-name.vue @@ -1,5 +1,5 @@ diff --git a/frontend/src/modules/onboard/pages/onboard-plans-page.vue b/frontend/src/modules/onboard/pages/onboard-plans-page.vue new file mode 100644 index 0000000000..dfd3eafee2 --- /dev/null +++ b/frontend/src/modules/onboard/pages/onboard-plans-page.vue @@ -0,0 +1,40 @@ + + + + + diff --git a/frontend/src/modules/onboard/types/OnboardStepsConfig.ts b/frontend/src/modules/onboard/types/OnboardStepsConfig.ts index 1d7da78114..2812049815 100644 --- a/frontend/src/modules/onboard/types/OnboardStepsConfig.ts +++ b/frontend/src/modules/onboard/types/OnboardStepsConfig.ts @@ -2,11 +2,11 @@ export interface OnboardStepConfig { name: string; component: any; textColor: (currentStep: number) => { - [key: string]: boolean - } + [key: string]: boolean; + }; bgColor: (currentStep: number) => { - [key: string]: boolean - } + [key: string]: boolean; + }; cta: string; ctaTooltip?: string; submitActionInfo?: string; diff --git a/frontend/src/modules/organization/components/form/organization-form-emails-item.vue b/frontend/src/modules/organization/components/form/organization-form-emails-item.vue new file mode 100644 index 0000000000..850eb7aa01 --- /dev/null +++ b/frontend/src/modules/organization/components/form/organization-form-emails-item.vue @@ -0,0 +1,61 @@ + + + + + diff --git a/frontend/src/modules/organization/components/form/organization-form-emails.vue b/frontend/src/modules/organization/components/form/organization-form-emails.vue new file mode 100644 index 0000000000..8ceb51e353 --- /dev/null +++ b/frontend/src/modules/organization/components/form/organization-form-emails.vue @@ -0,0 +1,86 @@ + + + + + diff --git a/frontend/src/modules/organization/components/form/organization-form-identities.vue b/frontend/src/modules/organization/components/form/organization-form-identities.vue index 44cd408546..bfa64802c8 100644 --- a/frontend/src/modules/organization/components/form/organization-form-identities.vue +++ b/frontend/src/modules/organization/components/form/organization-form-identities.vue @@ -1,108 +1,53 @@ @@ -702,7 +791,10 @@ import revenueRange from '@/modules/organization/config/enrichment/revenueRange' import AppTagList from '@/modules/tag/components/tag-list.vue'; import { ClickOutside as vClickOutside } from 'element-plus'; import AppSvg from '@/shared/svg/svg.vue'; -import AppOrganizationIdentities from '../organization-identities.vue'; +import CrEnrichmentSneakPeakContent from '@/shared/modules/enrichment/components/enrichment-sneak-peak-content.vue'; +import { mapGetters } from '@/shared/vuex/vuex.helpers'; +import Plans from '@/security/plans'; +import AppIdentitiesHorizontalListOrganizations from '@/shared/modules/identities/components/identities-horizontal-list-organizations.vue'; import AppOrganizationListToolbar from './organization-list-toolbar.vue'; import AppOrganizationName from '../organization-name.vue'; import AppOrganizationDropdownContent from '../organization-dropdown-content.vue'; @@ -744,10 +836,17 @@ const isTableHovered = ref(false); const isCursorDown = ref(false); const showOrganizationDropdownPopover = ref(false); -const OrganizationDropdownPopover = ref(null); const actionBtnRefs = ref({}); const selectedActionOrganization = ref(null); +const showEnrichmentPopover = ref(false); +const enrichmentRefs = ref({}); +const selectedEnrichmentAttribute = ref(null); + +const { currentTenant } = mapGetters('auth'); + +const isEnrichEnabled = computed(() => currentTenant.value?.plan !== Plans.values.essential); + const pagination = computed({ get() { return props.pagination; @@ -814,6 +913,44 @@ const onActionBtnClick = (organization) => { } }; +const setEnrichmentAttributesRef = (el, id) => { + if (el) { + enrichmentRefs.value[id] = el; + } +}; + +const handleCellMouseEnter = (row, column) => { + const validValues = ['industry', 'size', 'revenueRange', 'founded', 'employeeGrowthRate', 'tags']; + + if (validValues.includes(column.property)) { + showEnrichmentPopover.value = true; + selectedEnrichmentAttribute.value = `${row.id}-${column.property}`; + } +}; + +const onColumnHeaderMouseOver = (id) => { + showEnrichmentPopover.value = true; + selectedEnrichmentAttribute.value = id; +}; + +const handleCellMouseLeave = (_row, column) => { + const validValues = ['industry', 'size', 'revenueRange', 'founded', 'employeeGrowthRate', 'tags']; + + if (!validValues.includes(column.property)) { + closeEnrichmentPopover(); + } +}; + +const closeEnrichmentPopover = (ev) => { + if (ev?.toElement?.id !== 'popover-content') { + showEnrichmentPopover.value = false; + + setTimeout(() => { + selectedEnrichmentAttribute.value = null; + }, 100); + } +}; + const closeDropdown = () => { showOrganizationDropdownPopover.value = false; diff --git a/frontend/src/modules/organization/components/list/organization-list-toolbar.vue b/frontend/src/modules/organization/components/list/organization-list-toolbar.vue index 06ca2822fe..81cdd390b5 100644 --- a/frontend/src/modules/organization/components/list/organization-list-toolbar.vue +++ b/frontend/src/modules/organization/components/list/organization-list-toolbar.vue @@ -111,6 +111,7 @@ const organizationStore = useOrganizationStore(); const { selectedOrganizations, filters, + mergedOrganizations, } = storeToRefs(organizationStore); const { fetchOrganizations } = organizationStore; @@ -175,23 +176,33 @@ const handleDoDestroyAllWithConfirm = () => ConfirmDialog({ const handleMergeOrganizations = async () => { const [firstOrganization, secondOrganization] = selectedOrganizations.value; - Message.info( - null, - { - title: 'Organizations are being merged', - }, - ); - OrganizationService.mergeOrganizations(firstOrganization.id, secondOrganization.id) .then(() => { Message.closeAll(); - Message.success('Organizations merged successfuly'); + + organizationStore + .addMergedOrganizations(firstOrganization.id, secondOrganization.id); + + const processesRunning = Object.keys(mergedOrganizations.value).length; + + Message.info(null, { + title: 'Organizations merging in progress', + message: processesRunning > 1 ? `${processesRunning} processes running` : null, + }); fetchOrganizations({ reload: true }); }) - .catch(() => { + .catch((error) => { Message.closeAll(); - Message.error('There was an error merging organizations'); + + if (error.response.status === 404) { + Message.success('Organizations already merged or deleted', { + message: `Sorry, the organizations you are trying to merge might have already been merged or deleted. + Please refresh to see the updated information.`, + }); + } else { + Message.error('There was an error merging organizations'); + } }); }; diff --git a/frontend/src/modules/organization/components/organization-actions.vue b/frontend/src/modules/organization/components/organization-actions.vue new file mode 100644 index 0000000000..b644951ada --- /dev/null +++ b/frontend/src/modules/organization/components/organization-actions.vue @@ -0,0 +1,131 @@ + + + + + + + diff --git a/frontend/src/modules/organization/components/organization-dropdown-content.vue b/frontend/src/modules/organization/components/organization-dropdown-content.vue index 18246caa5a..38c12a1b40 100644 --- a/frontend/src/modules/organization/components/organization-dropdown-content.vue +++ b/frontend/src/modules/organization/components/organization-dropdown-content.vue @@ -1,6 +1,7 @@ @@ -55,6 +72,10 @@ import { computed, defineProps } from 'vue'; import enrichmentAttributes from '@/modules/organization/config/enrichment'; import { AttributeType } from '@/modules/organization/types/Attributes'; import AppSvg from '@/shared/svg/svg.vue'; +import CrEnrichmentSneakPeak from '@/shared/modules/enrichment/components/enrichment-sneak-peak.vue'; +import CrEnrichmentSneakPeakContent from '@/shared/modules/enrichment/components/enrichment-sneak-peak-content.vue'; +import { mapGetters } from '@/shared/vuex/vuex.helpers'; +import Plans from '@/security/plans'; const props = defineProps({ organization: { @@ -63,8 +84,16 @@ const props = defineProps({ }, }); +const { currentTenant } = mapGetters('auth'); +const isEnrichmentEnabled = computed(() => currentTenant.value.plan !== Plans.values.essential); + const visibleAttributes = computed(() => enrichmentAttributes - .filter((a) => ((props.organization[a.name] && a.type !== AttributeType.ARRAY && a.type !== AttributeType.JSON) - || (a.type === AttributeType.ARRAY && props.organization[a.name]?.length) - || (a.type === AttributeType.JSON && props.organization[a.name] && Object.keys(props.organization[a.name]))) && a.showInAttributes)); + .filter((a) => { + if (!isEnrichmentEnabled.value) { + return a.enrichmentSneakPeak && a.showInAttributes; + } + return ((props.organization[a.name] && a.type !== AttributeType.ARRAY && a.type !== AttributeType.JSON) + || (a.type === AttributeType.ARRAY && props.organization[a.name]?.length) + || (a.type === AttributeType.JSON && props.organization[a.name] && Object.keys(props.organization[a.name]))) && a.showInAttributes; + })); diff --git a/frontend/src/modules/organization/components/view/_aside/_aside-identities-extra.vue b/frontend/src/modules/organization/components/view/_aside/_aside-identities-extra.vue new file mode 100644 index 0000000000..738b276857 --- /dev/null +++ b/frontend/src/modules/organization/components/view/_aside/_aside-identities-extra.vue @@ -0,0 +1,191 @@ + + + diff --git a/frontend/src/modules/organization/components/view/_aside/_aside-identities.vue b/frontend/src/modules/organization/components/view/_aside/_aside-identities.vue new file mode 100644 index 0000000000..bcc8168d4a --- /dev/null +++ b/frontend/src/modules/organization/components/view/_aside/_aside-identities.vue @@ -0,0 +1,105 @@ + + + diff --git a/frontend/src/modules/organization/components/view/organization-view-aside.vue b/frontend/src/modules/organization/components/view/organization-view-aside.vue index dd027a5622..7704853e4b 100644 --- a/frontend/src/modules/organization/components/view/organization-view-aside.vue +++ b/frontend/src/modules/organization/components/view/organization-view-aside.vue @@ -1,104 +1,14 @@ + + + + diff --git a/frontend/src/shared/modules/enrichment/components/enrichment-sneak-peak.vue b/frontend/src/shared/modules/enrichment/components/enrichment-sneak-peak.vue new file mode 100644 index 0000000000..b6076f741a --- /dev/null +++ b/frontend/src/shared/modules/enrichment/components/enrichment-sneak-peak.vue @@ -0,0 +1,44 @@ + + + + + + + diff --git a/frontend/src/shared/modules/enrichment/constants/sneak-peak-popover.ts b/frontend/src/shared/modules/enrichment/constants/sneak-peak-popover.ts new file mode 100644 index 0000000000..12307befd8 --- /dev/null +++ b/frontend/src/shared/modules/enrichment/constants/sneak-peak-popover.ts @@ -0,0 +1,19 @@ +import { + EnrichSneakPeakPopoverType, + EnrichSneakPeakPopoverContent, +} from '@/shared/modules/enrichment/types/SneakPeakPopover'; + +export const popoverContent: Record = { + [EnrichSneakPeakPopoverType.CONTACT]: { + title: 'Contact enrichment', + body: 'Get more insights about this contact by enriching it with valuable ' + + 'details such as seniority level, OSS contributions, skills and much more.', + link: 'https://docs.crowd.dev/docs/guides/contacts/contact-enrichment', + }, + [EnrichSneakPeakPopoverType.ORGANIZATION]: { + title: 'Organization enrichment', + body: 'Get more insights about this organization by enriching it with valuable details such ' + + 'as headcount, industry, location, and more...', + link: 'https://docs.crowd.dev/docs/guides/organizations/organization-enrichment', + }, +}; diff --git a/frontend/src/shared/modules/enrichment/types/SneakPeakPopover.ts b/frontend/src/shared/modules/enrichment/types/SneakPeakPopover.ts new file mode 100644 index 0000000000..9a42e22ca2 --- /dev/null +++ b/frontend/src/shared/modules/enrichment/types/SneakPeakPopover.ts @@ -0,0 +1,9 @@ +export enum EnrichSneakPeakPopoverType { + CONTACT = 'contact', + ORGANIZATION = 'organization' +} +export interface EnrichSneakPeakPopoverContent { + title: string; + body: string; + link: string; +} diff --git a/frontend/src/shared/modules/filters/config/apiFilterRenderer/boolean.filter.renderer.ts b/frontend/src/shared/modules/filters/config/apiFilterRenderer/boolean.filter.renderer.ts index 61303f7ac1..89263e2dd4 100644 --- a/frontend/src/shared/modules/filters/config/apiFilterRenderer/boolean.filter.renderer.ts +++ b/frontend/src/shared/modules/filters/config/apiFilterRenderer/boolean.filter.renderer.ts @@ -2,6 +2,6 @@ import { BooleanFilterValue } from '@/shared/modules/filters/types/filterTypes/B export const booleanApiFilterRenderer = (property: string, { value }: BooleanFilterValue): any[] => [ { - [property]: { eq: value }, + [property]: value ? { eq: true } : { not: true }, }, ]; diff --git a/frontend/src/shared/modules/filters/config/apiFilterRenderer/date.filter.renderer.ts b/frontend/src/shared/modules/filters/config/apiFilterRenderer/date.filter.renderer.ts index c7774d6129..84f53a1891 100644 --- a/frontend/src/shared/modules/filters/config/apiFilterRenderer/date.filter.renderer.ts +++ b/frontend/src/shared/modules/filters/config/apiFilterRenderer/date.filter.renderer.ts @@ -44,7 +44,7 @@ export const dateApiFilterRenderer = (property: string, { value, operator }: Dat if (['last24h'].includes(value as string)) { parsedValue = mappedValue as string; - } else if ([FilterDateOperator.GT].includes(operator)) { + } else if ([FilterDateOperator.GT, FilterDateOperator.GTE].includes(operator)) { parsedValue = moment.utc(mappedValue).endOf('day').toISOString(); } diff --git a/frontend/src/shared/modules/filters/config/constants/date.constants.ts b/frontend/src/shared/modules/filters/config/constants/date.constants.ts index 3eaffcdd22..33834633b6 100644 --- a/frontend/src/shared/modules/filters/config/constants/date.constants.ts +++ b/frontend/src/shared/modules/filters/config/constants/date.constants.ts @@ -7,6 +7,7 @@ export enum FilterDateOperator { NE = 'ne', LT = 'lt', GT = 'gt', + GTE = 'gte', BETWEEN = 'between', NOT_BETWEEN = 'not-between', } diff --git a/frontend/src/shared/modules/filters/services/custom-attributes.service.ts b/frontend/src/shared/modules/filters/services/custom-attributes.service.ts index 4cf753ba66..9e6eecd20f 100644 --- a/frontend/src/shared/modules/filters/services/custom-attributes.service.ts +++ b/frontend/src/shared/modules/filters/services/custom-attributes.service.ts @@ -112,7 +112,7 @@ export const customAttributesService = () => { } // Multiselect type if (attribute.type === FilterCustomAttributeType.MULTISELECT - || (attribute.type === FilterCustomAttributeType.SPECIAL && attribute.options.length > 0)) { + || (attribute.type === FilterCustomAttributeType.SPECIAL && attribute.options?.length > 0)) { filters[attribute.name] = { id: attribute.name, label: attribute.label, @@ -122,10 +122,10 @@ export const customAttributesService = () => { hideIncludeSwitch: true, options: [ { - options: attribute.options.map((option) => ({ + options: attribute.options?.map((option) => ({ value: option, label: option, - })), + })) || [], }, ], }, diff --git a/frontend/src/shared/modules/identities/components/identities-horizontal-list-members.vue b/frontend/src/shared/modules/identities/components/identities-horizontal-list-members.vue new file mode 100644 index 0000000000..c27a8ee6f0 --- /dev/null +++ b/frontend/src/shared/modules/identities/components/identities-horizontal-list-members.vue @@ -0,0 +1,32 @@ + + + + + diff --git a/frontend/src/shared/modules/identities/components/identities-horizontal-list-organizations.vue b/frontend/src/shared/modules/identities/components/identities-horizontal-list-organizations.vue new file mode 100644 index 0000000000..61684cd604 --- /dev/null +++ b/frontend/src/shared/modules/identities/components/identities-horizontal-list-organizations.vue @@ -0,0 +1,32 @@ + + + + + diff --git a/frontend/src/shared/modules/identities/components/identities-horizontal-list.vue b/frontend/src/shared/modules/identities/components/identities-horizontal-list.vue new file mode 100644 index 0000000000..b94d1c6d3b --- /dev/null +++ b/frontend/src/shared/modules/identities/components/identities-horizontal-list.vue @@ -0,0 +1,112 @@ + + + + + diff --git a/frontend/src/shared/modules/identities/components/identities-vertical-list-members.vue b/frontend/src/shared/modules/identities/components/identities-vertical-list-members.vue new file mode 100644 index 0000000000..f9d401eea4 --- /dev/null +++ b/frontend/src/shared/modules/identities/components/identities-vertical-list-members.vue @@ -0,0 +1,39 @@ + + + + + diff --git a/frontend/src/shared/modules/identities/components/identities-vertical-list-organizations.vue b/frontend/src/shared/modules/identities/components/identities-vertical-list-organizations.vue new file mode 100644 index 0000000000..c8df99e6a4 --- /dev/null +++ b/frontend/src/shared/modules/identities/components/identities-vertical-list-organizations.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/frontend/src/shared/modules/identities/components/identities-vertical-list.vue b/frontend/src/shared/modules/identities/components/identities-vertical-list.vue new file mode 100644 index 0000000000..4b3ac7f05e --- /dev/null +++ b/frontend/src/shared/modules/identities/components/identities-vertical-list.vue @@ -0,0 +1,116 @@ + + + + + diff --git a/frontend/src/shared/modules/identities/config/identitiesOrder/member/index.ts b/frontend/src/shared/modules/identities/config/identitiesOrder/member/index.ts new file mode 100644 index 0000000000..f02d97fd77 --- /dev/null +++ b/frontend/src/shared/modules/identities/config/identitiesOrder/member/index.ts @@ -0,0 +1,9 @@ +import list from './list'; +import profile from './profile'; +import suggestions from './suggestions'; + +export default { + list, + profile, + suggestions, +}; diff --git a/frontend/src/shared/modules/identities/config/identitiesOrder/member/list.ts b/frontend/src/shared/modules/identities/config/identitiesOrder/member/list.ts new file mode 100644 index 0000000000..83795b6d91 --- /dev/null +++ b/frontend/src/shared/modules/identities/config/identitiesOrder/member/list.ts @@ -0,0 +1,18 @@ +import { Platform } from '@/shared/modules/platform/types/Platform'; + +export default [ + Platform.GITHUB, + Platform.DISCORD, + Platform.HACKER_NEWS, + Platform.LINKEDIN, + Platform.TWITTER, + Platform.SLACK, + Platform.DEVTO, + Platform.REDDIT, + Platform.STACK_OVERFLOW, + Platform.DISCOURSE, + Platform.HUBSPOT, + Platform.GIT, + Platform.GROUPS_IO, + Platform.CUSTOM, +]; diff --git a/frontend/src/shared/modules/identities/config/identitiesOrder/member/profile.ts b/frontend/src/shared/modules/identities/config/identitiesOrder/member/profile.ts new file mode 100644 index 0000000000..83795b6d91 --- /dev/null +++ b/frontend/src/shared/modules/identities/config/identitiesOrder/member/profile.ts @@ -0,0 +1,18 @@ +import { Platform } from '@/shared/modules/platform/types/Platform'; + +export default [ + Platform.GITHUB, + Platform.DISCORD, + Platform.HACKER_NEWS, + Platform.LINKEDIN, + Platform.TWITTER, + Platform.SLACK, + Platform.DEVTO, + Platform.REDDIT, + Platform.STACK_OVERFLOW, + Platform.DISCOURSE, + Platform.HUBSPOT, + Platform.GIT, + Platform.GROUPS_IO, + Platform.CUSTOM, +]; diff --git a/frontend/src/shared/modules/identities/config/identitiesOrder/member/suggestions.ts b/frontend/src/shared/modules/identities/config/identitiesOrder/member/suggestions.ts new file mode 100644 index 0000000000..83795b6d91 --- /dev/null +++ b/frontend/src/shared/modules/identities/config/identitiesOrder/member/suggestions.ts @@ -0,0 +1,18 @@ +import { Platform } from '@/shared/modules/platform/types/Platform'; + +export default [ + Platform.GITHUB, + Platform.DISCORD, + Platform.HACKER_NEWS, + Platform.LINKEDIN, + Platform.TWITTER, + Platform.SLACK, + Platform.DEVTO, + Platform.REDDIT, + Platform.STACK_OVERFLOW, + Platform.DISCOURSE, + Platform.HUBSPOT, + Platform.GIT, + Platform.GROUPS_IO, + Platform.CUSTOM, +]; diff --git a/frontend/src/shared/modules/identities/config/identitiesOrder/organization/index.ts b/frontend/src/shared/modules/identities/config/identitiesOrder/organization/index.ts new file mode 100644 index 0000000000..f02d97fd77 --- /dev/null +++ b/frontend/src/shared/modules/identities/config/identitiesOrder/organization/index.ts @@ -0,0 +1,9 @@ +import list from './list'; +import profile from './profile'; +import suggestions from './suggestions'; + +export default { + list, + profile, + suggestions, +}; diff --git a/frontend/src/shared/modules/identities/config/identitiesOrder/organization/list.ts b/frontend/src/shared/modules/identities/config/identitiesOrder/organization/list.ts new file mode 100644 index 0000000000..1aceb5547e --- /dev/null +++ b/frontend/src/shared/modules/identities/config/identitiesOrder/organization/list.ts @@ -0,0 +1,10 @@ +import { Platform } from '@/shared/modules/platform/types/Platform'; + +export default [ + Platform.GITHUB, + Platform.LINKEDIN, + Platform.TWITTER, + Platform.CRUNCHBASE, + Platform.HUBSPOT, + Platform.CUSTOM, +]; diff --git a/frontend/src/shared/modules/identities/config/identitiesOrder/organization/profile.ts b/frontend/src/shared/modules/identities/config/identitiesOrder/organization/profile.ts new file mode 100644 index 0000000000..1aceb5547e --- /dev/null +++ b/frontend/src/shared/modules/identities/config/identitiesOrder/organization/profile.ts @@ -0,0 +1,10 @@ +import { Platform } from '@/shared/modules/platform/types/Platform'; + +export default [ + Platform.GITHUB, + Platform.LINKEDIN, + Platform.TWITTER, + Platform.CRUNCHBASE, + Platform.HUBSPOT, + Platform.CUSTOM, +]; diff --git a/frontend/src/shared/modules/identities/config/identitiesOrder/organization/suggestions.ts b/frontend/src/shared/modules/identities/config/identitiesOrder/organization/suggestions.ts new file mode 100644 index 0000000000..1aceb5547e --- /dev/null +++ b/frontend/src/shared/modules/identities/config/identitiesOrder/organization/suggestions.ts @@ -0,0 +1,10 @@ +import { Platform } from '@/shared/modules/platform/types/Platform'; + +export default [ + Platform.GITHUB, + Platform.LINKEDIN, + Platform.TWITTER, + Platform.CRUNCHBASE, + Platform.HUBSPOT, + Platform.CUSTOM, +]; diff --git a/frontend/src/shared/modules/identities/config/useMemberIdentities.ts b/frontend/src/shared/modules/identities/config/useMemberIdentities.ts new file mode 100644 index 0000000000..120668ac99 --- /dev/null +++ b/frontend/src/shared/modules/identities/config/useMemberIdentities.ts @@ -0,0 +1,142 @@ +import { CrowdIntegrations } from '@/integrations/integrations-config'; +import { Member } from '@/modules/member/types/Member'; +import { Platform } from '@/shared/modules/platform/types/Platform'; + +export default ({ + member, + order, +}: { + member: Partial; + order: Platform[]; +}) => { + const { username = {}, attributes = {}, emails = [] } = member || {}; + + const getIdentityHandles = (platform: string) => { + if (platform === Platform.CUSTOM) { + const customPlatforms = Object.keys(username).filter( + (p) => (!order.includes(p) || p === Platform.CUSTOM) + && p !== Platform.EMAIL + && p !== Platform.EMAILS, + ); + + return customPlatforms.flatMap((p) => username[p].map((u) => ({ + platform: p, + url: null, + name: u, + }))); + } + + return username[platform] + ? username[platform].map((u) => ({ + platform, + url: null, + name: u, + })) + : []; + }; + + const getIdentityLink = (identity: { + platform: string; + url: string; + name: string; + }, platform: string) => { + if (!CrowdIntegrations.getConfig(platform)?.showProfileLink) { + return null; + } + + return ( + identity.url + ?? CrowdIntegrations.getConfig(platform)?.url({ + username: identity.name, + attributes, + }) + ?? attributes?.url?.[platform] + ); + }; + + const getIdentities = (): { + [key: string]: { + handle: string; + link: string; + }[]; + } => order.reduce((acc, platform) => { + const handles = getIdentityHandles(platform); + + if (platform === Platform.CUSTOM && handles.length) { + const sortedCustomIdentities = handles.sort((a, b) => { + const platformComparison = a.platform.localeCompare(b.platform); + + if (platformComparison === 0) { + // If platforms are equal, sort by name + return a.name.localeCompare(b.name); + } + + return platformComparison; // Otherwise, sort by platform + }); + + sortedCustomIdentities.forEach((identity) => { + if (acc[identity.platform]?.length) { + acc[identity.platform].push({ + handle: identity.name, + link: getIdentityLink(identity, platform), + }); + } else { + acc[identity.platform] = [ + { + handle: identity.name, + link: getIdentityLink(identity, platform), + }, + ]; + } + }); + } else { + const platformHandlesValues = handles.map((identity) => ({ + handle: identity.name, + link: getIdentityLink(identity, platform), + })); + + if (platformHandlesValues.length) { + acc[platform] = platformHandlesValues; + } + } + + return acc; + }, {}); + + const getEmails = (): { + handle: string; + link: string; + }[] => { + const rootEmails = (emails || []) + .filter((e) => !!e) + .map((e) => ({ + link: `mailto:${e}`, + handle: e, + })); + + const usernameEmail = username.email + ? username.email + .filter((e) => !!e) + .map((e) => ({ + link: null, + handle: e, + })) + : []; + + const usernameEmails = username.emails + ? username.emails + .filter((e) => !!e) + .map((e) => ({ + link: `mailto:${e}`, + handle: e, + })) + : []; + + return [...rootEmails, ...usernameEmail, ...usernameEmails]; + }; + + return { + getIdentities, + getEmails, + }; +}; diff --git a/frontend/src/shared/modules/identities/config/useOrganizationIdentities.ts b/frontend/src/shared/modules/identities/config/useOrganizationIdentities.ts new file mode 100644 index 0000000000..81a5749297 --- /dev/null +++ b/frontend/src/shared/modules/identities/config/useOrganizationIdentities.ts @@ -0,0 +1,134 @@ +import { CrowdIntegrations } from '@/integrations/integrations-config'; +import { withHttp } from '@/utils/string'; +import { Organization } from '@/modules/organization/types/Organization'; +import { Platform } from '@/shared/modules/platform/types/Platform'; + +export default ({ + organization, + order, +}: { + organization: Partial; + order: Platform[]; +}) => { + const { + identities = [], + emails = [], + phoneNumbers = [], + } = organization || {}; + + const getIdentityHandles = (platform: string) => { + const parsedIdentities = identities?.length ? identities : []; + + if (platform === Platform.CUSTOM) { + const customPlatforms = parsedIdentities.filter( + (i) => (!order.includes(i.platform) || i.platform === Platform.CUSTOM) + && i.platform !== Platform.EMAIL + && i.platform !== Platform.EMAILS, + ); + + return customPlatforms; + } + + return parsedIdentities.filter((i) => i.platform === platform) || []; + }; + + const getIdentities = (): { + [key: string]: { + handle: string; + link: string; + }[]; + } => order.reduce((acc, p) => { + const handles = getIdentityHandles(p); + + if ( + (p === Platform.CUSTOM || p === Platform.PHONE_NUMBERS) + && handles.length + ) { + const sortedCustomIdentities = handles.sort((a, b) => { + const platformComparison = a.platform.localeCompare(b.platform); + + if (platformComparison === 0) { + // If platforms are equal, sort by name + return a.name.localeCompare(b.name); + } + + return platformComparison; // Otherwise, sort by platform + }); + + sortedCustomIdentities.forEach((i) => { + if (acc[i.platform]?.length) { + acc[i.platform].push({ + handle: i.name, + link: i.url ? withHttp(i.url) : null, + }); + } else { + acc[i.platform] = [ + { + handle: i.name, + link: i.url ? withHttp(i.url) : null, + }, + ]; + } + }); + } else { + const handlesValues = handles.map((i) => ({ + handle: + CrowdIntegrations.getConfig(i.platform)?.organization?.handle(i) + ?? i.name + ?? CrowdIntegrations.getConfig(i.platform)?.name + ?? i.platform, + link: i.url ? withHttp(i.url) : null, + })); + + if (handlesValues.length) { + acc[p] = handlesValues; + } + } + + return acc; + }, {}); + + const getEmails = (): { + handle: string; + link: string; + }[] => { + const parsedIdentities = identities?.length ? identities : []; + + const rootEmails = (emails || []) + .filter((e) => !!e) + .map((e) => ({ + link: `mailto:${e}`, + handle: e, + })); + + const identitiesEmails = parsedIdentities + .filter((i) => i.platform === 'emails') + .map((i) => ({ + link: i.url ? `mailto:${i.url}` : null, + handle: i.name, + })); + + const identitiesEmail = parsedIdentities + .filter((i) => i.platform === 'email') + .map((i) => ({ + link: i.url ? `mailto:${i.url}` : null, + handle: i.name, + })); + + return [...rootEmails, ...identitiesEmails, ...identitiesEmail]; + }; + + const getPhoneNumbers = (): { + handle: string; + link: string; + }[] => (phoneNumbers || []).map((p) => ({ + link: `tel:${p}`, + handle: p, + })); + + return { + getIdentities, + getEmails, + getPhoneNumbers, + }; +}; diff --git a/frontend/src/shared/modules/platform/components/platform-icon.vue b/frontend/src/shared/modules/platform/components/platform-icon.vue new file mode 100644 index 0000000000..d46d93ff03 --- /dev/null +++ b/frontend/src/shared/modules/platform/components/platform-icon.vue @@ -0,0 +1,38 @@ + + + + + diff --git a/frontend/src/shared/modules/platform/components/platform-img.vue b/frontend/src/shared/modules/platform/components/platform-img.vue new file mode 100644 index 0000000000..3da8906d77 --- /dev/null +++ b/frontend/src/shared/modules/platform/components/platform-img.vue @@ -0,0 +1,33 @@ + + + + + diff --git a/frontend/src/shared/modules/platform/components/platform-svg.vue b/frontend/src/shared/modules/platform/components/platform-svg.vue new file mode 100644 index 0000000000..cd57246bad --- /dev/null +++ b/frontend/src/shared/modules/platform/components/platform-svg.vue @@ -0,0 +1,31 @@ + + + + + diff --git a/frontend/src/shared/modules/platform/components/platform.vue b/frontend/src/shared/modules/platform/components/platform.vue new file mode 100644 index 0000000000..0c6ab9f8d7 --- /dev/null +++ b/frontend/src/shared/modules/platform/components/platform.vue @@ -0,0 +1,89 @@ + + + + + + + diff --git a/frontend/src/shared/modules/platform/types/Platform.ts b/frontend/src/shared/modules/platform/types/Platform.ts new file mode 100644 index 0000000000..e4469d4012 --- /dev/null +++ b/frontend/src/shared/modules/platform/types/Platform.ts @@ -0,0 +1,20 @@ +export enum Platform { + GITHUB = 'github', + DISCORD = 'discord', + HACKER_NEWS = 'hackernews', + LINKEDIN = 'linkedin', + TWITTER = 'twitter', + SLACK = 'slack', + DEVTO = 'devto', + REDDIT = 'reddit', + STACK_OVERFLOW = 'stackOverflow', + DISCOURSE = 'discourse', + HUBSPOT = 'hubspot', + GIT = 'git', + GROUPS_IO = 'groupsio', + CUSTOM = 'custom', + EMAIL = 'email', + EMAILS = 'emails', + PHONE_NUMBERS = 'phoneNumbers', + CRUNCHBASE = 'crunchbase', +} diff --git a/frontend/src/shared/pagination/pagination-sorter.vue b/frontend/src/shared/pagination/pagination-sorter.vue index 42fbff9706..159ab21efe 100644 --- a/frontend/src/shared/pagination/pagination-sorter.vue +++ b/frontend/src/shared/pagination/pagination-sorter.vue @@ -112,10 +112,7 @@ const model = computed({ }); const computedOptions = computed(() => { - if ( - props.module === 'activity' - || props.module === 'conversation' - ) { + if (props.module === 'activity') { return [ { value: 'trending', @@ -128,6 +125,16 @@ const computedOptions = computed(() => { ]; } + if (props.module === 'conversation' + ) { + return [ + { + value: 'recentActivity', + label: 'Most recent activity', + }, + ]; + } + return [ { value: 20, label: '20' }, { value: 50, label: '50' }, @@ -181,6 +188,7 @@ const doExport = async () => { await showExportDialog({ tenantCsvExportCount, planExportCountMax, + badgeContent: pluralize('contact', props.total, true), }); await props.export(); diff --git a/frontend/src/shared/platform/platform-list.vue b/frontend/src/shared/platform/platform-list.vue deleted file mode 100644 index 7a60e0204b..0000000000 --- a/frontend/src/shared/platform/platform-list.vue +++ /dev/null @@ -1,87 +0,0 @@ - - - - - diff --git a/frontend/src/shared/platform/platform-popover.vue b/frontend/src/shared/platform/platform-popover.vue deleted file mode 100644 index 3948a90bc3..0000000000 --- a/frontend/src/shared/platform/platform-popover.vue +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - - diff --git a/frontend/src/shared/platform/platform-svg-icon.vue b/frontend/src/shared/platform/platform-svg-icon.vue deleted file mode 100644 index d61d0e911d..0000000000 --- a/frontend/src/shared/platform/platform-svg-icon.vue +++ /dev/null @@ -1,87 +0,0 @@ - - - - - diff --git a/frontend/src/shared/platform/platform.vue b/frontend/src/shared/platform/platform.vue deleted file mode 100644 index 50d96391a4..0000000000 --- a/frontend/src/shared/platform/platform.vue +++ /dev/null @@ -1,167 +0,0 @@ - - - - - - - diff --git a/frontend/src/shared/shared-module.js b/frontend/src/shared/shared-module.js index efba4575dd..6e3ca84ff1 100644 --- a/frontend/src/shared/shared-module.js +++ b/frontend/src/shared/shared-module.js @@ -14,7 +14,6 @@ import InlineSelectInput from '@/shared/form/inline-select-input.vue'; import Dialog from '@/shared/dialog/dialog.vue'; import EmptyStateCta from '@/shared/empty-state/empty-state-cta.vue'; import EmptyState from '@/shared/empty-state/empty-state.vue'; -import Platform from '@/shared/platform/platform.vue'; import Drawer from '@/shared/drawer/drawer.vue'; import AppLoader from '@/shared/loading/loader.vue'; import AppPageWrapper from '@/shared/layout/page-wrapper.vue'; @@ -41,7 +40,6 @@ export default { 'app-dialog': Dialog, 'app-empty-state-cta': EmptyStateCta, 'app-empty-state': EmptyState, - 'app-platform': Platform, 'app-drawer': Drawer, 'app-loader': AppLoader, 'app-page-wrapper': AppPageWrapper, diff --git a/frontend/src/shared/store/actions.js b/frontend/src/shared/store/actions.js index f8dfd81222..ca6cbbe36e 100644 --- a/frontend/src/shared/store/actions.js +++ b/frontend/src/shared/store/actions.js @@ -153,7 +153,7 @@ export default (moduleName, moduleService = null) => { }, async doUpdate({ commit }, { - id, values, successMessage, errorMessage, + id, values, successMessage, errorMessage, messageOptions, }) { try { commit('UPDATE_STARTED'); @@ -166,6 +166,7 @@ export default (moduleName, moduleService = null) => { commit('UPDATE_SUCCESS', response); Message.success( successMessage || i18n(`entities.${moduleName}.update.success`), + messageOptions, ); return response; diff --git a/frontend/src/shared/ui-kit/button/Button.stories.ts b/frontend/src/shared/ui-kit/button/Button.stories.ts new file mode 100644 index 0000000000..94b1a7ee63 --- /dev/null +++ b/frontend/src/shared/ui-kit/button/Button.stories.ts @@ -0,0 +1,268 @@ +import { buttonTypes } from '@/shared/ui-kit/button/types/ButtonType'; +import { buttonSizes } from '@/shared/ui-kit/button/types/ButtonSize'; +import { buttonNativeTypes } from '@/shared/ui-kit/button/types/ButtonNativeType'; +import CrButton from './Button.vue'; + +export default { + title: 'Crowd.dev/Button', + component: CrButton, + tags: ['autodocs'], + argTypes: { + // Props + type: { + description: 'Specifies button type', + defaultValue: 'primary', + control: 'select', + options: buttonTypes, + }, + size: { + description: 'Specifies button size', + defaultValue: 'medium', + control: 'select', + options: buttonSizes, + }, + iconOnly: { + description: 'If content includes only icon', + defaultValue: false, + control: 'boolean', + }, + loading: { + description: 'Specifies if button in loading state', + defaultValue: false, + control: 'boolean', + }, + loadingText: { + description: 'Specifies text displayed in loading state', + defaultValue: undefined, + control: 'text', + }, + disabled: { + description: 'Specifies if button is disabled', + defaultValue: false, + control: 'boolean', + }, + nativeType: { + description: 'Specifies button native HTML type', + defaultValue: 'button', + control: 'select', + options: buttonNativeTypes, + }, + + // Slots + default: { + description: 'Text or html content of the button', + control: { + type: null, + }, + }, + }, +}; + +export const Primary = { + label: 'Primary', + args: { + type: 'primary', + size: 'medium', + nativeType: 'button', + loading: false, + loadingText: '', + disabled: false, + iconOnly: false, + default: 'Button text', + }, +}; + +export const Secondary = { + args: { + type: 'secondary', + size: 'medium', + nativeType: 'button', + loading: false, + loadingText: '', + disabled: false, + iconOnly: false, + default: 'Button text', + }, +}; + +export const Tertiary = { + args: { + type: 'tertiary', + size: 'medium', + nativeType: 'button', + loading: false, + loadingText: '', + disabled: false, + iconOnly: false, + default: 'Button text', + }, +}; + +export const TertiaryGray = { + args: { + type: 'tertiary-gray', + size: 'medium', + nativeType: 'button', + loading: false, + loadingText: '', + disabled: false, + iconOnly: false, + default: 'Button text', + }, +}; + +export const TertiaryLightGray = { + args: { + type: 'tertiary-light-gray', + size: 'medium', + nativeType: 'button', + loading: false, + loadingText: '', + disabled: false, + iconOnly: false, + default: 'Button text', + }, +}; + +export const Info = { + args: { + type: 'info', + size: 'medium', + nativeType: 'button', + loading: false, + loadingText: '', + disabled: false, + iconOnly: false, + default: 'Button text', + }, +}; + +export const InfoTransparent = { + args: { + type: 'info-transparent', + size: 'medium', + nativeType: 'button', + loading: false, + loadingText: '', + disabled: false, + iconOnly: false, + default: 'Button text', + }, +}; + +export const Success = { + args: { + type: 'success', + size: 'medium', + nativeType: 'button', + loading: false, + loadingText: '', + disabled: false, + iconOnly: false, + default: 'Button text', + }, +}; + +export const SuccessTransparent = { + args: { + type: 'success-transparent', + size: 'medium', + nativeType: 'button', + loading: false, + loadingText: '', + disabled: false, + iconOnly: false, + default: 'Button text', + }, +}; + +export const Danger = { + args: { + type: 'danger', + size: 'medium', + nativeType: 'button', + loading: false, + loadingText: '', + disabled: false, + iconOnly: false, + default: 'Button text', + }, +}; + +export const DangerTransparent = { + args: { + type: 'danger-transparent', + size: 'medium', + nativeType: 'button', + loading: false, + loadingText: '', + disabled: false, + iconOnly: false, + default: 'Button text', + }, +}; + +export const Warning = { + args: { + type: 'warning', + size: 'medium', + nativeType: 'button', + loading: false, + loadingText: '', + disabled: false, + iconOnly: false, + default: 'Button text', + }, +}; + +export const WarningTransparent = { + args: { + type: 'warning-transparent', + size: 'medium', + nativeType: 'button', + loading: false, + loadingText: '', + disabled: false, + iconOnly: false, + default: 'Button text', + }, +}; + +export const Feature = { + args: { + type: 'feature', + size: 'medium', + nativeType: 'button', + loading: false, + loadingText: '', + disabled: false, + iconOnly: false, + default: 'Button text', + }, +}; + +export const FeatureTransparent = { + args: { + type: 'feature-transparent', + size: 'medium', + nativeType: 'button', + loading: false, + loadingText: '', + disabled: false, + iconOnly: false, + default: 'Button text', + }, +}; + +export const Loading = { + args: { + type: 'primary', + size: 'medium', + nativeType: 'button', + loading: true, + loadingText: 'Loading...', + disabled: false, + iconOnly: false, + default: 'Button text', + }, +}; diff --git a/frontend/src/shared/ui-kit/button/Button.vue b/frontend/src/shared/ui-kit/button/Button.vue new file mode 100644 index 0000000000..59ad693890 --- /dev/null +++ b/frontend/src/shared/ui-kit/button/Button.vue @@ -0,0 +1,47 @@ + + + + + diff --git a/frontend/src/shared/ui-kit/button/button.scss b/frontend/src/shared/ui-kit/button/button.scss new file mode 100644 index 0000000000..971167cbd5 --- /dev/null +++ b/frontend/src/shared/ui-kit/button/button.scss @@ -0,0 +1,510 @@ +.c-btn { + color: var(--cr-btn-text); + background: var(--cr-btn-background); + border: rem(1) solid var(--cr-btn-border); + box-shadow: var(--cr-btn-shadow); + font-size: var(--cr-btn-font-size); + line-height: var(--cr-btn-line-height); + padding: var(--cr-btn-padding); + border-radius: var(--cr-btn-border-radius); + height: var(--cr-btn-height); + @apply relative select-none transition-all whitespace-nowrap cursor-pointer outline-none text-center font-semibold inline-flex items-center justify-center gap-2; + + &:hover{ + color: var(--cr-btn-hover-text); + background: var(--cr-btn-hover-background); + border-color: var(--cr-btn-hover-border); + } + + &:active{ + color: var(--cr-btn-active-text); + background: var(--cr-btn-active-background); + border-color: var(--cr-btn-active-border); + } + + &:disabled, &.is-disabled{ + color: var(--cr-btn-disabled-text); + background: var(--cr-btn-disabled-background); + border-color: var(--cr-btn-disabled-border); + @apply cursor-default; + } + + &__loader{ + @apply animate-spin; + } + + &.is-loading{ + color: var(--cr-btn-loading-text); + background: var(--cr-btn-loading-background); + border-color: var(--cr-btn-loading-border); + + // hide icons on loading + [class^="ri-"]:not(.c-btn__loader), .c-icon{ + @apply hidden; + } + } + + [class^="ri-"], .c-icon{ + height: var(--cr-btn-icon); + width: var(--cr-btn-icon); + font-size: var(--cr-btn-icon); + @apply flex items-center justify-center font-normal; + } + + /* Icon only */ + &--icon{ + width: var(--cr-btn-height); + padding: 0 !important; + } + + /* Icon only */ + &--icon{ + width: var(--cr-btn-height); + padding: 0 !important; + } + + /* Button Sizes */ + &--tiny { + --cr-btn-font-size: var(--cr-btn-tiny-font-size); + --cr-btn-line-height: var(--cr-btn-tiny-line-height); + --cr-btn-height: var(--cr-btn-tiny-height); + --cr-btn-border-radius: var(--cr-btn-tiny-border-radius); + --cr-btn-padding: #{rem(0)} var(--cr-btn-tiny-padding); + --cr-btn-icon: var(--cr-btn-tiny-icon); + } + + &--small { + --cr-btn-font-size: var(--cr-btn-small-font-size); + --cr-btn-line-height: var(--cr-btn-small-line-height); + --cr-btn-height: var(--cr-btn-small-height); + --cr-btn-border-radius: var(--cr-btn-small-border-radius); + --cr-btn-padding: #{rem(0)} var(--cr-btn-small-padding); + --cr-btn-icon: var(--cr-btn-small-icon); + } + + &--medium { + --cr-btn-font-size: var(--cr-btn-medium-font-size); + --cr-btn-line-height: var(--cr-btn-medium-line-height); + --cr-btn-height: var(--cr-btn-medium-height); + --cr-btn-border-radius: var(--cr-btn-medium-border-radius); + --cr-btn-padding: #{rem(0)} var(--cr-btn-medium-padding); + --cr-btn-icon: var(--cr-btn-medium-icon); + } + + &--large { + --cr-btn-font-size: var(--cr-btn-large-font-size); + --cr-btn-line-height: var(--cr-btn-large-line-height); + --cr-btn-height: var(--cr-btn-large-height); + --cr-btn-border-radius: var(--cr-btn-large-border-radius); + --cr-btn-padding: #{rem(0)} var(--cr-btn-large-padding); + --cr-btn-icon: var(--cr-btn-large-icon); + } + + /* Button Styles */ + &--primary { + --cr-btn-text: var(--cr-btn-primary-text); + --cr-btn-background: var(--cr-btn-primary-background); + --cr-btn-border: var(--cr-btn-primary-border); + --cr-btn-shadow: var(--cr-btn-primary-shadow); + + // Hover + --cr-btn-hover-text: var(--cr-btn-primary-hover-text); + --cr-btn-hover-background: var(--cr-btn-primary-hover-background); + --cr-btn-hover-border: var(--cr-btn-primary-hover-border); + + // Active + --cr-btn-active-text: var(--cr-btn-primary-active-text); + --cr-btn-active-background: var(--cr-btn-primary-active-background); + --cr-btn-active-border: var(--cr-btn-primary-active-border); + + // Disabled + --cr-btn-disabled-text: var(--cr-btn-primary-disabled-text); + --cr-btn-disabled-background: var(--cr-btn-primary-disabled-background); + --cr-btn-disabled-border: var(--cr-btn-primary-disabled-border); + + // Loading + --cr-btn-loading-text: var(--cr-btn-primary-loading-text); + --cr-btn-loading-background: var(--cr-btn-primary-); + --cr-btn-loading-border: var(--cr-btn-primary-loading-border); + } + + &--secondary { + --cr-btn-text: var(--cr-btn-secondary-text); + --cr-btn-background: var(--cr-btn-secondary-background); + --cr-btn-border: var(--cr-btn-secondary-border); + --cr-btn-shadow: var(--cr-btn-secondary-shadow); + + // Hover + --cr-btn-hover-text: var(--cr-btn-secondary-hover-text); + --cr-btn-hover-background: var(--cr-btn-secondary-hover-background); + --cr-btn-hover-border: var(--cr-btn-secondary-hover-border); + + // Active + --cr-btn-active-text: var(--cr-btn-secondary-active-text); + --cr-btn-active-background: var(--cr-btn-secondary-active-background); + --cr-btn-active-border: var(--cr-btn-secondary-active-border); + + // Disabled + --cr-btn-disabled-text: var(--cr-btn-secondary-disabled-text); + --cr-btn-disabled-background: var(--cr-btn-secondary-disabled-background); + --cr-btn-disabled-border: var(--cr-btn-secondary-disabled-border); + + // Loading + --cr-btn-loading-text: var(--cr-btn-secondary-loading-text); + --cr-btn-loading-background: var(--cr-btn-secondary-); + --cr-btn-loading-border: var(--cr-btn-secondary-loading-border); + } + + &--tertiary { + --cr-btn-text: var(--cr-btn-tertiary-text); + --cr-btn-background: var(--cr-btn-tertiary-background); + --cr-btn-border: var(--cr-btn-tertiary-border); + --cr-btn-shadow: var(--cr-btn-tertiary-shadow); + + // Hover + --cr-btn-hover-text: var(--cr-btn-tertiary-hover-text); + --cr-btn-hover-background: var(--cr-btn-tertiary-hover-background); + --cr-btn-hover-border: var(--cr-btn-tertiary-hover-border); + + // Active + --cr-btn-active-text: var(--cr-btn-tertiary-active-text); + --cr-btn-active-background: var(--cr-btn-tertiary-active-background); + --cr-btn-active-border: var(--cr-btn-tertiary-active-border); + + // Disabled + --cr-btn-disabled-text: var(--cr-btn-tertiary-disabled-text); + --cr-btn-disabled-background: var(--cr-btn-tertiary-disabled-background); + --cr-btn-disabled-border: var(--cr-btn-tertiary-disabled-border); + + // Loading + --cr-btn-loading-text: var(--cr-btn-tertiary-loading-text); + --cr-btn-loading-background: var(--cr-btn-tertiary-); + --cr-btn-loading-border: var(--cr-btn-tertiary-loading-border); + } + + &--tertiary-gray { + --cr-btn-text: var(--cr-btn-tertiary-gray-text); + --cr-btn-background: var(--cr-btn-tertiary-gray-background); + --cr-btn-border: var(--cr-btn-tertiary-gray-border); + --cr-btn-shadow: var(--cr-btn-tertiary-gray-shadow); + + // Hover + --cr-btn-hover-text: var(--cr-btn-tertiary-gray-hover-text); + --cr-btn-hover-background: var(--cr-btn-tertiary-gray-hover-background); + --cr-btn-hover-border: var(--cr-btn-tertiary-gray-hover-border); + + // Active + --cr-btn-active-text: var(--cr-btn-tertiary-gray-active-text); + --cr-btn-active-background: var(--cr-btn-tertiary-gray-active-background); + --cr-btn-active-border: var(--cr-btn-tertiary-gray-active-border); + + // Disabled + --cr-btn-disabled-text: var(--cr-btn-tertiary-gray-disabled-text); + --cr-btn-disabled-background: var(--cr-btn-tertiary-gray-disabled-background); + --cr-btn-disabled-border: var(--cr-btn-tertiary-gray-disabled-border); + + // Loading + --cr-btn-loading-text: var(--cr-btn-tertiary-gray-loading-text); + --cr-btn-loading-background: var(--cr-btn-tertiary-gray-); + --cr-btn-loading-border: var(--cr-btn-tertiary-gray-loading-border); + } + + &--tertiary-light-gray { + --cr-btn-text: var(--cr-btn-tertiary-light-gray-text); + --cr-btn-background: var(--cr-btn-tertiary-light-gray-background); + --cr-btn-border: var(--cr-btn-tertiary-light-gray-border); + --cr-btn-shadow: var(--cr-btn-tertiary-light-gray-shadow); + + // Hover + --cr-btn-hover-text: var(--cr-btn-tertiary-light-gray-hover-text); + --cr-btn-hover-background: var(--cr-btn-tertiary-light-gray-hover-background); + --cr-btn-hover-border: var(--cr-btn-tertiary-light-gray-hover-border); + + // Active + --cr-btn-active-text: var(--cr-btn-tertiary-light-gray-active-text); + --cr-btn-active-background: var(--cr-btn-tertiary-light-gray-active-background); + --cr-btn-active-border: var(--cr-btn-tertiary-light-gray-active-border); + + // Disabled + --cr-btn-disabled-text: var(--cr-btn-tertiary-light-gray-disabled-text); + --cr-btn-disabled-background: var(--cr-btn-tertiary-light-gray-disabled-background); + --cr-btn-disabled-border: var(--cr-btn-tertiary-light-gray-disabled-border); + + // Loading + --cr-btn-loading-text: var(--cr-btn-tertiary-light-gray-loading-text); + --cr-btn-loading-background: var(--cr-btn-tertiary-light-gray-); + --cr-btn-loading-border: var(--cr-btn-tertiary-light-gray-loading-border); + } + + &--info { + --cr-btn-text: var(--cr-btn-info-text); + --cr-btn-background: var(--cr-btn-info-background); + --cr-btn-border: var(--cr-btn-info-border); + --cr-btn-shadow: var(--cr-btn-info-shadow); + + // Hover + --cr-btn-hover-text: var(--cr-btn-info-hover-text); + --cr-btn-hover-background: var(--cr-btn-info-hover-background); + --cr-btn-hover-border: var(--cr-btn-info-hover-border); + + // Active + --cr-btn-active-text: var(--cr-btn-info-active-text); + --cr-btn-active-background: var(--cr-btn-info-active-background); + --cr-btn-active-border: var(--cr-btn-info-active-border); + + // Disabled + --cr-btn-disabled-text: var(--cr-btn-info-disabled-text); + --cr-btn-disabled-background: var(--cr-btn-info-disabled-background); + --cr-btn-disabled-border: var(--cr-btn-info-disabled-border); + + // Loading + --cr-btn-loading-text: var(--cr-btn-info-loading-text); + --cr-btn-loading-background: var(--cr-btn-info-); + --cr-btn-loading-border: var(--cr-btn-info-loading-border); + } + + &--info-transparent { + --cr-btn-text: var(--cr-btn-info-transparent-text); + --cr-btn-background: var(--cr-btn-info-transparent-background); + --cr-btn-border: var(--cr-btn-info-transparent-border); + --cr-btn-shadow: var(--cr-btn-info-transparent-shadow); + + // Hover + --cr-btn-hover-text: var(--cr-btn-info-transparent-hover-text); + --cr-btn-hover-background: var(--cr-btn-info-transparent-hover-background); + --cr-btn-hover-border: var(--cr-btn-info-transparent-hover-border); + + // Active + --cr-btn-active-text: var(--cr-btn-info-transparent-active-text); + --cr-btn-active-background: var(--cr-btn-info-transparent-active-background); + --cr-btn-active-border: var(--cr-btn-info-transparent-active-border); + + // Disabled + --cr-btn-disabled-text: var(--cr-btn-info-transparent-disabled-text); + --cr-btn-disabled-background: var(--cr-btn-info-transparent-disabled-background); + --cr-btn-disabled-border: var(--cr-btn-info-transparent-disabled-border); + + // Loading + --cr-btn-loading-text: var(--cr-btn-info-transparent-loading-text); + --cr-btn-loading-background: var(--cr-btn-info-transparent-); + --cr-btn-loading-border: var(--cr-btn-info-transparent-loading-border); + } + + &--success { + --cr-btn-text: var(--cr-btn-success-text); + --cr-btn-background: var(--cr-btn-success-background); + --cr-btn-border: var(--cr-btn-success-border); + --cr-btn-shadow: var(--cr-btn-success-shadow); + + // Hover + --cr-btn-hover-text: var(--cr-btn-success-hover-text); + --cr-btn-hover-background: var(--cr-btn-success-hover-background); + --cr-btn-hover-border: var(--cr-btn-success-hover-border); + + // Active + --cr-btn-active-text: var(--cr-btn-success-active-text); + --cr-btn-active-background: var(--cr-btn-success-active-background); + --cr-btn-active-border: var(--cr-btn-success-active-border); + + // Disabled + --cr-btn-disabled-text: var(--cr-btn-success-disabled-text); + --cr-btn-disabled-background: var(--cr-btn-success-disabled-background); + --cr-btn-disabled-border: var(--cr-btn-success-disabled-border); + + // Loading + --cr-btn-loading-text: var(--cr-btn-success-loading-text); + --cr-btn-loading-background: var(--cr-btn-success-); + --cr-btn-loading-border: var(--cr-btn-success-loading-border); + } + + &--success-transparent { + --cr-btn-text: var(--cr-btn-success-transparent-text); + --cr-btn-background: var(--cr-btn-success-transparent-background); + --cr-btn-border: var(--cr-btn-success-transparent-border); + --cr-btn-shadow: var(--cr-btn-success-transparent-shadow); + + // Hover + --cr-btn-hover-text: var(--cr-btn-success-transparent-hover-text); + --cr-btn-hover-background: var(--cr-btn-success-transparent-hover-background); + --cr-btn-hover-border: var(--cr-btn-success-transparent-hover-border); + + // Active + --cr-btn-active-text: var(--cr-btn-success-transparent-active-text); + --cr-btn-active-background: var(--cr-btn-success-transparent-active-background); + --cr-btn-active-border: var(--cr-btn-success-transparent-active-border); + + // Disabled + --cr-btn-disabled-text: var(--cr-btn-success-transparent-disabled-text); + --cr-btn-disabled-background: var(--cr-btn-success-transparent-disabled-background); + --cr-btn-disabled-border: var(--cr-btn-success-transparent-disabled-border); + + // Loading + --cr-btn-loading-text: var(--cr-btn-success-transparent-loading-text); + --cr-btn-loading-background: var(--cr-btn-success-transparent-); + --cr-btn-loading-border: var(--cr-btn-success-transparent-loading-border); + } + + &--danger { + --cr-btn-text: var(--cr-btn-danger-text); + --cr-btn-background: var(--cr-btn-danger-background); + --cr-btn-border: var(--cr-btn-danger-border); + --cr-btn-shadow: var(--cr-btn-danger-shadow); + + // Hover + --cr-btn-hover-text: var(--cr-btn-danger-hover-text); + --cr-btn-hover-background: var(--cr-btn-danger-hover-background); + --cr-btn-hover-border: var(--cr-btn-danger-hover-border); + + // Active + --cr-btn-active-text: var(--cr-btn-danger-active-text); + --cr-btn-active-background: var(--cr-btn-danger-active-background); + --cr-btn-active-border: var(--cr-btn-danger-active-border); + + // Disabled + --cr-btn-disabled-text: var(--cr-btn-danger-disabled-text); + --cr-btn-disabled-background: var(--cr-btn-danger-disabled-background); + --cr-btn-disabled-border: var(--cr-btn-danger-disabled-border); + + // Loading + --cr-btn-loading-text: var(--cr-btn-danger-loading-text); + --cr-btn-loading-background: var(--cr-btn-danger-); + --cr-btn-loading-border: var(--cr-btn-danger-loading-border); + } + + &--danger-transparent { + --cr-btn-text: var(--cr-btn-danger-transparent-text); + --cr-btn-background: var(--cr-btn-danger-transparent-background); + --cr-btn-border: var(--cr-btn-danger-transparent-border); + --cr-btn-shadow: var(--cr-btn-danger-transparent-shadow); + + // Hover + --cr-btn-hover-text: var(--cr-btn-danger-transparent-hover-text); + --cr-btn-hover-background: var(--cr-btn-danger-transparent-hover-background); + --cr-btn-hover-border: var(--cr-btn-danger-transparent-hover-border); + + // Active + --cr-btn-active-text: var(--cr-btn-danger-transparent-active-text); + --cr-btn-active-background: var(--cr-btn-danger-transparent-active-background); + --cr-btn-active-border: var(--cr-btn-danger-transparent-active-border); + + // Disabled + --cr-btn-disabled-text: var(--cr-btn-danger-transparent-disabled-text); + --cr-btn-disabled-background: var(--cr-btn-danger-transparent-disabled-background); + --cr-btn-disabled-border: var(--cr-btn-danger-transparent-disabled-border); + + // Loading + --cr-btn-loading-text: var(--cr-btn-danger-transparent-loading-text); + --cr-btn-loading-background: var(--cr-btn-danger-transparent-); + --cr-btn-loading-border: var(--cr-btn-danger-transparent-loading-border); + } + + &--warning { + --cr-btn-text: var(--cr-btn-warning-text); + --cr-btn-background: var(--cr-btn-warning-background); + --cr-btn-border: var(--cr-btn-warning-border); + --cr-btn-shadow: var(--cr-btn-warning-shadow); + + // Hover + --cr-btn-hover-text: var(--cr-btn-warning-hover-text); + --cr-btn-hover-background: var(--cr-btn-warning-hover-background); + --cr-btn-hover-border: var(--cr-btn-warning-hover-border); + + // Active + --cr-btn-active-text: var(--cr-btn-warning-active-text); + --cr-btn-active-background: var(--cr-btn-warning-active-background); + --cr-btn-active-border: var(--cr-btn-warning-active-border); + + // Disabled + --cr-btn-disabled-text: var(--cr-btn-warning-disabled-text); + --cr-btn-disabled-background: var(--cr-btn-warning-disabled-background); + --cr-btn-disabled-border: var(--cr-btn-warning-disabled-border); + + // Loading + --cr-btn-loading-text: var(--cr-btn-warning-loading-text); + --cr-btn-loading-background: var(--cr-btn-warning-); + --cr-btn-loading-border: var(--cr-btn-warning-loading-border); + } + + &--warning-transparent { + --cr-btn-text: var(--cr-btn-warning-transparent-text); + --cr-btn-background: var(--cr-btn-warning-transparent-background); + --cr-btn-border: var(--cr-btn-warning-transparent-border); + --cr-btn-shadow: var(--cr-btn-warning-transparent-shadow); + + // Hover + --cr-btn-hover-text: var(--cr-btn-warning-transparent-hover-text); + --cr-btn-hover-background: var(--cr-btn-warning-transparent-hover-background); + --cr-btn-hover-border: var(--cr-btn-warning-transparent-hover-border); + + // Active + --cr-btn-active-text: var(--cr-btn-warning-transparent-active-text); + --cr-btn-active-background: var(--cr-btn-warning-transparent-active-background); + --cr-btn-active-border: var(--cr-btn-warning-transparent-active-border); + + // Disabled + --cr-btn-disabled-text: var(--cr-btn-warning-transparent-disabled-text); + --cr-btn-disabled-background: var(--cr-btn-warning-transparent-disabled-background); + --cr-btn-disabled-border: var(--cr-btn-warning-transparent-disabled-border); + + // Loading + --cr-btn-loading-text: var(--cr-btn-warning-transparent-loading-text); + --cr-btn-loading-background: var(--cr-btn-warning-transparent-); + --cr-btn-loading-border: var(--cr-btn-warning-transparent-loading-border); + } + + &--feature { + --cr-btn-text: var(--cr-btn-feature-text); + --cr-btn-background: var(--cr-btn-feature-background); + --cr-btn-border: var(--cr-btn-feature-border); + --cr-btn-shadow: var(--cr-btn-feature-shadow); + + // Hover + --cr-btn-hover-text: var(--cr-btn-feature-hover-text); + --cr-btn-hover-background: var(--cr-btn-feature-hover-background); + --cr-btn-hover-border: var(--cr-btn-feature-hover-border); + + // Active + --cr-btn-active-text: var(--cr-btn-feature-active-text); + --cr-btn-active-background: var(--cr-btn-feature-active-background); + --cr-btn-active-border: var(--cr-btn-feature-active-border); + + // Disabled + --cr-btn-disabled-text: var(--cr-btn-feature-disabled-text); + --cr-btn-disabled-background: var(--cr-btn-feature-disabled-background); + --cr-btn-disabled-border: var(--cr-btn-feature-disabled-border); + + // Loading + --cr-btn-loading-text: var(--cr-btn-feature-loading-text); + --cr-btn-loading-background: var(--cr-btn-feature-); + --cr-btn-loading-border: var(--cr-btn-feature-loading-border); + } + + &--feature-transparent { + --cr-btn-text: var(--cr-btn-feature-transparent-text); + --cr-btn-background: var(--cr-btn-feature-transparent-background); + --cr-btn-border: var(--cr-btn-feature-transparent-border); + --cr-btn-shadow: var(--cr-btn-feature-transparent-shadow); + + // Hover + --cr-btn-hover-text: var(--cr-btn-feature-transparent-hover-text); + --cr-btn-hover-background: var(--cr-btn-feature-transparent-hover-background); + --cr-btn-hover-border: var(--cr-btn-feature-transparent-hover-border); + + // Active + --cr-btn-active-text: var(--cr-btn-feature-transparent-active-text); + --cr-btn-active-background: var(--cr-btn-feature-transparent-active-background); + --cr-btn-active-border: var(--cr-btn-feature-transparent-active-border); + + // Disabled + --cr-btn-disabled-text: var(--cr-btn-feature-transparent-disabled-text); + --cr-btn-disabled-background: var(--cr-btn-feature-transparent-disabled-background); + --cr-btn-disabled-border: var(--cr-btn-feature-transparent-disabled-border); + + // Loading + --cr-btn-loading-text: var(--cr-btn-feature-transparent-loading-text); + --cr-btn-loading-background: var(--cr-btn-feature-transparent-); + --cr-btn-loading-border: var(--cr-btn-feature-transparent-loading-border); + } +} + + diff --git a/frontend/src/shared/ui-kit/button/types/ButtonNativeType.ts b/frontend/src/shared/ui-kit/button/types/ButtonNativeType.ts new file mode 100644 index 0000000000..55e3daa934 --- /dev/null +++ b/frontend/src/shared/ui-kit/button/types/ButtonNativeType.ts @@ -0,0 +1,7 @@ +export const buttonNativeTypes = [ + 'button', + 'submit', + 'reset', +] as const; + +export type ButtonNativeType = typeof buttonNativeTypes[number]; diff --git a/frontend/src/shared/ui-kit/button/types/ButtonSize.ts b/frontend/src/shared/ui-kit/button/types/ButtonSize.ts new file mode 100644 index 0000000000..7569756a28 --- /dev/null +++ b/frontend/src/shared/ui-kit/button/types/ButtonSize.ts @@ -0,0 +1,8 @@ +export const buttonSizes = [ + 'tiny', + 'small', + 'medium', + 'large', +] as const; + +export type ButtonSize = typeof buttonSizes[number]; diff --git a/frontend/src/shared/ui-kit/button/types/ButtonType.ts b/frontend/src/shared/ui-kit/button/types/ButtonType.ts new file mode 100644 index 0000000000..afd965557f --- /dev/null +++ b/frontend/src/shared/ui-kit/button/types/ButtonType.ts @@ -0,0 +1,19 @@ +export const buttonTypes = [ + 'primary', + 'secondary', + 'tertiary', + 'tertiary-gray', + 'tertiary-light-gray', + 'info', + 'info-transparent', + 'success', + 'success-transparent', + 'danger', + 'danger-transparent', + 'warning', + 'warning-transparent', + 'feature', + 'feature-transparent', +] as const; + +export type ButtonType = typeof buttonTypes[number]; diff --git a/frontend/src/shared/ui-kit/card/Card.stories.ts b/frontend/src/shared/ui-kit/card/Card.stories.ts new file mode 100644 index 0000000000..99c2684940 --- /dev/null +++ b/frontend/src/shared/ui-kit/card/Card.stories.ts @@ -0,0 +1,38 @@ +import CrCard from './Card.vue'; + +export default { + title: 'Crowd.dev/Card', + component: CrCard, + tags: ['autodocs'], + argTypes: { + // Slots + default: { + description: 'Text or html content of the button', + control: { + type: null, + }, + }, + }, +}; + +export const Default = { + label: 'Primary', + args: { + default: 'This is card content', + }, + parameters: { + backgrounds: { + default: 'crowd-background', + values: [ + { + name: 'crowd-background', + value: '#f8f8f8', + }, + ], + }, + }, + render: () => ({ + components: { CrCard }, + template: '
This is card content
', + }), +}; diff --git a/frontend/src/shared/ui-kit/card/Card.vue b/frontend/src/shared/ui-kit/card/Card.vue new file mode 100644 index 0000000000..1d208dc050 --- /dev/null +++ b/frontend/src/shared/ui-kit/card/Card.vue @@ -0,0 +1,11 @@ + + + diff --git a/frontend/src/shared/ui-kit/card/card.scss b/frontend/src/shared/ui-kit/card/card.scss new file mode 100644 index 0000000000..c6c457430b --- /dev/null +++ b/frontend/src/shared/ui-kit/card/card.scss @@ -0,0 +1,8 @@ +.c-card { + box-shadow: var(--cr-card-shadow); + border-radius: var(--cr-card-radius); + background: var(--cr-card-background); + border: var(--cr-card-border); +} + + diff --git a/frontend/src/shared/ui-kit/checkbox/Checkbox.stories.ts b/frontend/src/shared/ui-kit/checkbox/Checkbox.stories.ts new file mode 100644 index 0000000000..912f184486 --- /dev/null +++ b/frontend/src/shared/ui-kit/checkbox/Checkbox.stories.ts @@ -0,0 +1,65 @@ +import { checkboxSizes } from '@/shared/ui-kit/checkbox/types/CheckboxSize'; +import CrCheckbox from './Checkbox.vue'; + +export default { + title: 'Crowd.dev/Checkbox', + component: CrCheckbox, + tags: ['autodocs'], + argTypes: { + // Props + size: { + description: 'Specifies checkbox size', + defaultValue: 'medium', + control: 'select', + options: checkboxSizes, + }, + modelValue: { + description: 'Checkbox value', + control: { + type: null, + }, + }, + value: { + description: 'Value for checkbox when checked', + control: { + type: null, + }, + }, + disabled: { + description: 'Specifies if checkbox is disabled', + defaultValue: false, + control: 'boolean', + }, + multiple: { + description: 'Specifies if checkbox is disabled', + defaultValue: false, + control: 'boolean', + }, + + // Slots + default: { + description: 'Text or html content of the checkbox', + control: { + type: null, + }, + }, + + // Events + 'update:modelValue': { + description: 'Event triggered when value changes', + control: { + type: null, + }, + }, + }, +}; + +export const Primary = { + label: 'Primary', + args: { + size: 'medium', + disabled: false, + multiple: false, + default: 'Checkbox text', + }, +}; diff --git a/frontend/src/shared/ui-kit/checkbox/Checkbox.vue b/frontend/src/shared/ui-kit/checkbox/Checkbox.vue new file mode 100644 index 0000000000..3802da56e4 --- /dev/null +++ b/frontend/src/shared/ui-kit/checkbox/Checkbox.vue @@ -0,0 +1,50 @@ + + + + + diff --git a/frontend/src/shared/ui-kit/checkbox/checkbox.scss b/frontend/src/shared/ui-kit/checkbox/checkbox.scss new file mode 100644 index 0000000000..6c51de24db --- /dev/null +++ b/frontend/src/shared/ui-kit/checkbox/checkbox.scss @@ -0,0 +1,95 @@ +.c-checkbox { + font-size: var(--cr-checkbox-font-size); + line-height: var(--cr-checkbox-line-height); + font-weight: var(--cr-checkbox-text-font-weight); + color: var(--cr-checkbox-text-color); + @apply flex flex-wrap relative; + + input { + height: var(--cr-checkbox-size); + width: var(--cr-checkbox-size); + border: rem(1) solid var(--cr-checkbox-border); + background: var(--cr-checkbox-background); + border-radius: var(--cr-checkbox-border-radius); + box-shadow: var(--cr-checkbox-shadow); + + --cr-checkbox-border: var(--cr-checkbox-unchecked-border); + --cr-checkbox-background: var(--cr-checkbox-unchecked-background); + + @apply transition-all appearance-none p-0 my-0 ml-0 inline-block mr-2 cursor-pointer; + + // Text + & + span{ + @apply cursor-pointer; + } + + // Icon + &:before{ + content: "\eb7b"; + font-family: 'remixicon', serif; + position: absolute; + left: 0; + top: 0; + color: var(--cr-checkbox-icon); + line-height: var(--cr-checkbox-size); + width: var(--cr-checkbox-size); + font-size: var(--cr-checkbox-size); + + --cr-checkbox-icon: var(--cr-checkbox-unchecked-icon); + } + + // Checked + &:checked{ + --cr-checkbox-border: var(--cr-checkbox-checked-border); + --cr-checkbox-background: var(--cr-checkbox-checked-background); + --cr-checkbox-icon: var(--cr-checkbox-checked-icon); + } + + // Disabled + &:disabled { + --cr-checkbox-border: var(--cr-checkbox-disabled-unchecked-border); + --cr-checkbox-background: var(--cr-checkbox-disabled-unchecked-background); + --cr-checkbox-icon: var(--cr-checkbox-disabled-unchecked-icon); + @apply cursor-not-allowed; + + &:checked { + --cr-checkbox-border: var(--cr-checkbox-disabled-checked-border); + --cr-checkbox-background: var(--cr-checkbox-disabled-checked-background); + --cr-checkbox-icon: var(--cr-checkbox-disabled-checked-icon); + } + + & + span{ + @apply cursor-not-allowed; + } + } + } + + // Checkbox sizes + &--small { + --cr-checkbox-size: var(--cr-checkbox-small-size); + --cr-checkbox-font-size: var(--cr-checkbox-small-font-size); + --cr-checkbox-line-height: var(--cr-checkbox-small-line-height); + } + + &--medium { + --cr-checkbox-size: var(--cr-checkbox-medium-size); + --cr-checkbox-font-size: var(--cr-checkbox-medium-font-size); + --cr-checkbox-line-height: var(--cr-checkbox-medium-line-height); + } + + // Multiple state + // Change icon to subtract-line + &--multiple { + input:before{ + content: "\f1af"; + } + } + + p{ + font-size: var(--cr-checkbox-description-font-size); + line-height: var(--cr-checkbox-description-line-height); + font-weight: var(--cr-checkbox-description-font-weight); + color: var(--cr-checkbox-description-color); + margin-top: var(--cr-checkbox-description-spacing); + } +} diff --git a/frontend/src/shared/ui-kit/checkbox/types/CheckboxSize.ts b/frontend/src/shared/ui-kit/checkbox/types/CheckboxSize.ts new file mode 100644 index 0000000000..888c91ce53 --- /dev/null +++ b/frontend/src/shared/ui-kit/checkbox/types/CheckboxSize.ts @@ -0,0 +1,6 @@ +export const checkboxSizes = [ + 'small', + 'medium', +] as const; + +export type CheckboxSize = typeof checkboxSizes[number]; diff --git a/frontend/src/shared/ui-kit/index.scss b/frontend/src/shared/ui-kit/index.scss new file mode 100644 index 0000000000..6e94be8cdf --- /dev/null +++ b/frontend/src/shared/ui-kit/index.scss @@ -0,0 +1,4 @@ +@import 'button/button'; +@import 'card/card'; +@import 'checkbox/checkbox'; + diff --git a/frontend/src/utils/date.js b/frontend/src/utils/date.js index 4df488fded..4f2b0ba797 100644 --- a/frontend/src/utils/date.js +++ b/frontend/src/utils/date.js @@ -56,7 +56,13 @@ export const getTrialDate = (tenant) => { 'days', ); - return `Trial (${daysLeft < 0 ? 0 : daysLeft} days left)`; + return `Trial (${daysLeft < 0 ? 0 : daysLeft + 1} days left)`; +}; +export const isTrialExpired = (tenant) => { + if (config.isCommunityVersion) { + return false; + } + return !tenant.plan || (tenant.isTrialPlan && moment().isAfter(moment(tenant.trialEndsAt))); }; export const isCurrentDateAfterGivenWorkingDays = (date, workingDays = 3) => { diff --git a/frontend/tailwind.config.js b/frontend/tailwind.config.js index 8ce378f3ac..ac0c6f5332 100644 --- a/frontend/tailwind.config.js +++ b/frontend/tailwind.config.js @@ -1,3 +1,7 @@ +const { getThemeReplacementsValues } = require('./.tailwind/colorConverter.js'); + +const themeReplacements = getThemeReplacementsValues(); + module.exports = { content: [ './index.html', @@ -13,142 +17,142 @@ module.exports = { min: '768px', max: '1280px' }, - lg: { - min: '1280px' - } + lg: '1024px', + xl: '1280px' }, colors: { - transparent: 'transparent', + transparent: 'var(--cr-color-transparent)', current: 'currentColor', - black: '#140505', - white: '#fff', - background: '#f8f8f8', + black: 'var(--cr-color-black)', + white: 'var(--cr-color-white)', + background: 'var(--cr-color-background)', brand: { - 900: '#2F1009', - 800: '#5D2012', - 700: '#8C2F1C', - 600: '#BA3F25', - 500: '#E94F2E', - 400: '#ED7258', - 300: '#F29582', - 200: '#F6B9AB', - 100: '#FBDCD5', - 50: '#FDEDEA', - 25: '#FDF6F4' + 900: 'var(--cr-color-brand-900)', + 800: 'var(--cr-color-brand-800)', + 700: 'var(--cr-color-brand-700)', + 600: 'var(--cr-color-brand-600)', + 500: 'var(--cr-color-brand-500)', + 400: 'var(--cr-color-brand-400)', + 300: 'var(--cr-color-brand-300)', + 200: 'var(--cr-color-brand-200)', + 100: 'var(--cr-color-brand-100)', + 50: 'var(--cr-color-brand-50)', + 25: 'var(--cr-color-brand-25)', }, gray: { - 1000: '#000000', - 900: '#111827', - 800: '#1F2937', - 700: '#374151', - 600: '#4B5563', - 500: '#6B7280', - 400: '#9CA3AF', - 300: '#D1D5DB', - 200: '#E5E7EB', - 100: '#F3F4F6', - 50: '#F9FAFB' + 1000: 'var(--cr-color-gray-1000)', + 900: 'var(--cr-color-gray-900)', + 800: 'var(--cr-color-gray-800)', + 700: 'var(--cr-color-gray-700)', + 600: 'var(--cr-color-gray-600)', + 500: 'var(--cr-color-gray-500)', + 400: 'var(--cr-color-gray-400)', + 300: 'var(--cr-color-gray-300)', + 200: 'var(--cr-color-gray-200)', + 100: 'var(--cr-color-gray-100)', + 50: 'var(--cr-color-gray-50)', }, blue: { - 900: '#1E3A8A', - 800: '#1E40AF', - 700: '#1D4ED8', - 600: '#2563EB', - 500: '#3B82F6', - 400: '#60A5FA', - 300: '#93C5FD', - 200: '#BFDBFE', - 100: '#DBEAFE', - 50: '#EFF6FF' + 900: 'var(--cr-color-blue-900)', + 800: 'var(--cr-color-blue-800)', + 700: 'var(--cr-color-blue-700)', + 600: 'var(--cr-color-blue-600)', + 500: 'var(--cr-color-blue-500)', + 400: 'var(--cr-color-blue-400)', + 300: 'var(--cr-color-blue-300)', + 200: 'var(--cr-color-blue-200)', + 100: 'var(--cr-color-blue-100)', + 50: 'var(--cr-color-blue-50)', }, red: { - 900: '#7F1D1D', - 800: '#991B1B', - 700: '#B91C1C', - 600: '#DC2626', - 500: '#EF4444', - 400: '#F87171', - 300: '#FCA5A5', - 200: '#FECACA', - 100: '#FEE2E2', - 50: '#FEF2F2' + 900: 'var(--cr-color-red-900)', + 800: 'var(--cr-color-red-800)', + 700: 'var(--cr-color-red-700)', + 600: 'var(--cr-color-red-600)', + 500: 'var(--cr-color-red-500)', + 400: 'var(--cr-color-red-400)', + 300: 'var(--cr-color-red-300)', + 200: 'var(--cr-color-red-200)', + 100: 'var(--cr-color-red-100)', + 50: 'var(--cr-color-red-50)', }, yellow: { - 900: '#78350F', - 800: '#92400E', - 700: '#B45309', - 600: '#D97706', - 500: '#F59E0B', - 400: '#FBBF24', - 300: '#FCD34D', - 200: '#FDE68A', - 100: '#FEF3C7', - 50: '#FFFBEB' + 900: 'var(--cr-color-yellow-900)', + 800: 'var(--cr-color-yellow-800)', + 700: 'var(--cr-color-yellow-700)', + 600: 'var(--cr-color-yellow-600)', + 500: 'var(--cr-color-yellow-500)', + 400: 'var(--cr-color-yellow-400)', + 300: 'var(--cr-color-yellow-300)', + 200: 'var(--cr-color-yellow-200)', + 100: 'var(--cr-color-yellow-100)', + 50: 'var(--cr-color-yellow-50)', }, green: { - 900: '#14532D', - 800: '#166534', - 700: '#15803D', - 600: '#16A34A', - 500: '#10B981', - 400: '#4ADE80', - 300: '#86EFAC', - 200: '#BBF7D0', - 100: '#DCFCE7', - 50: '#F0FDF4' - }, - darkgreen: { - 900: '#059669' + 1000: 'var(--cr-color-green-1000)', + 900: 'var(--cr-color-green-900)', + 800: 'var(--cr-color-green-800)', + 700: 'var(--cr-color-green-700)', + 600: 'var(--cr-color-green-600)', + 500: 'var(--cr-color-green-500)', + 400: 'var(--cr-color-green-400)', + 300: 'var(--cr-color-green-300)', + 200: 'var(--cr-color-green-200)', + 100: 'var(--cr-color-green-100)', + 50: 'var(--cr-color-green-50)', }, teal: { - 900: '#134E4A', - 800: '#115E59', - 700: '#0F766E', - 600: '#0D9488', - 500: '#14B8A6', - 400: '#2DD4BF', - 300: '#5EEAD4', - 200: '#99F6E4', - 100: '#CCFBF1', - 50: '#F0FDFA' + 900: 'var(--color-teal-900)', + 800: 'var(--color-teal-800)', + 700: 'var(--color-teal-700)', + 600: 'var(--color-teal-600)', + 500: 'var(--color-teal-500)', + 400: 'var(--color-teal-400)', + 300: 'var(--color-teal-300)', + 200: 'var(--color-teal-200)', + 100: 'var(--color-teal-100)', + 50: 'var(--color-teal-50)', }, purple: { - 900: '#4C1D95', - 800: '#5B21B6', - 700: '#6D28D9', - 600: '#7C3AED', - 500: '#8B5CF6', - 400: '#A78BFA', - 300: '#C4B5FD', - 200: '#DDD6FE', - 100: '#EDE9FE', - 50: '#F5F3FF' + 900: 'var(--color-purple-900)', + 800: 'var(--color-purple-800)', + 700: 'var(--color-purple-700)', + 600: 'var(--color-purple-600)', + 500: 'var(--color-purple-500)', + 400: 'var(--color-purple-400)', + 300: 'var(--color-purple-300)', + 200: 'var(--color-purple-200)', + 100: 'var(--color-purple-100)', + 50: 'var(--color-purple-50)', }, cyan: { - 900: '#164E63', - 800: '#155E75', - 700: '#0E7490', - 600: '#0891B2', - 500: '#06B6D4', - 400: '#22D3EE', - 300: '#67E8F9', - 200: '#A5F3FC', - 100: '#CFFAFE', - 50: '#ECFEFF' + 900: 'var(--color-cyan-900)', + 800: 'var(--color-cyan-800)', + 700: 'var(--color-cyan-700)', + 600: 'var(--color-cyan-600)', + 500: 'var(--color-cyan-500)', + 400: 'var(--color-cyan-400)', + 300: 'var(--color-cyan-300)', + 200: 'var(--color-cyan-200)', + 100: 'var(--color-cyan-100)', + 50: 'var(--color-cyan-50)', }, orange: { - 900: '#7C2D12', - 800: '#9A3412', - 700: '#C2410C', - 600: '#EA580C', - 500: '#F97316', - 400: '#FB923C', - 300: '#FDBA74', - 200: '#FED7AA', - 100: '#FFEDD5', - 50: '#FFF7ED' + 900: 'var(--color-orange-900)', + 800: 'var(--color-orange-800)', + 700: 'var(--color-orange-700)', + 600: 'var(--color-orange-600)', + 500: 'var(--color-orange-500)', + 400: 'var(--color-orange-400)', + 300: 'var(--color-orange-300)', + 200: 'var(--color-orange-200)', + 100: 'var(--color-orange-100)', + 50: 'var(--color-orange-50)', } }, + configViewer: { + themeReplacements + }, columns: { auto: 'auto', 1: '1', diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fe2e44b2e3..5949901f03 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6,6 +6,52 @@ settings: importers: + .github/actions/node: + dependencies: + '@actions/core': + specifier: ^1.10.1 + version: 1.10.1 + '@actions/exec': + specifier: ^1.1.1 + version: 1.1.1 + '@actions/io': + specifier: ^1.1.3 + version: 1.1.3 + dotenv: + specifier: 8.2.0 + version: 8.2.0 + devDependencies: + '@types/node': + specifier: ^20.10.6 + version: 20.10.7 + '@typescript-eslint/eslint-plugin': + specifier: ^6.7.4 + version: 6.13.1(@typescript-eslint/parser@6.13.1)(eslint@8.54.0)(typescript@5.3.2) + '@typescript-eslint/parser': + specifier: ^6.7.4 + version: 6.13.1(eslint@8.54.0)(typescript@5.3.2) + '@vercel/ncc': + specifier: ^0.38.1 + version: 0.38.1 + eslint: + specifier: ^8.50.0 + version: 8.54.0 + eslint-config-prettier: + specifier: ^9.0.0 + version: 9.0.0(eslint@8.54.0) + eslint-plugin-prettier: + specifier: ^5.0.0 + version: 5.0.1(eslint-config-prettier@9.0.0)(eslint@8.54.0)(prettier@3.1.0) + prettier: + specifier: ^3.0.3 + version: 3.1.0 + ts-node: + specifier: ^10.9.1 + version: 10.9.1(@types/node@20.10.7)(typescript@5.3.2) + typescript: + specifier: ^5.2.2 + version: 5.3.2 + backend: dependencies: '@aws-sdk/client-comprehend': @@ -32,9 +78,12 @@ importers: '@crowd/common': specifier: file:../services/libs/common version: file:services/libs/common + '@crowd/common_services': + specifier: file:../services/libs/common_services + version: file:services/libs/common_services '@crowd/cubejs': specifier: file:../services/libs/cubejs - version: file:services/libs/cubejs(bufferutil@4.0.8)(utf-8-validate@5.0.10) + version: file:services/libs/cubejs '@crowd/feature-flags': specifier: file:../services/libs/feature-flags version: file:services/libs/feature-flags @@ -90,8 +139,8 @@ importers: specifier: ^7.7.0 version: 7.7.0 '@sendgrid/mail': - specifier: 7.2.6 - version: 7.2.6 + specifier: ~8.1.0 + version: 8.1.0 '@slack/web-api': specifier: ^6.7.2 version: 6.10.0 @@ -159,7 +208,7 @@ importers: specifier: ^4.1.1 version: 4.2.0 discord.js: - specifier: ^14.7.1 + specifier: ^14.14.1 version: 14.14.1(bufferutil@4.0.8)(utf-8-validate@5.0.10) dotenv: specifier: 8.2.0 @@ -246,8 +295,8 @@ importers: specifier: 0.0.7 version: 0.0.7 peopledatalabs: - specifier: ^5.0.3 - version: 5.1.0 + specifier: ~6.1.5 + version: 6.1.5 pg: specifier: ^8.7.3 version: 8.11.3 @@ -470,6 +519,82 @@ importers: specifier: ^3.0.3 version: 3.1.0 + services/apps/cache_worker: + dependencies: + '@crowd/archetype-standard': + specifier: file:../../archetypes/standard + version: file:services/archetypes/standard(@swc/core@1.3.100)(@types/node@20.10.1)(typescript@5.3.2) + '@crowd/archetype-worker': + specifier: file:../../archetypes/worker + version: file:services/archetypes/worker(@swc/core@1.3.100)(@types/node@20.10.1)(typescript@5.3.2) + '@crowd/common': + specifier: file:../../libs/common + version: file:services/libs/common + '@crowd/cubejs': + specifier: file:../../libs/cubejs + version: file:services/libs/cubejs + '@crowd/feature-flags': + specifier: file:../../libs/feature-flags + version: file:services/libs/feature-flags + '@crowd/types': + specifier: file:../../libs/types + version: file:services/libs/types + '@temporalio/activity': + specifier: ~1.8.6 + version: 1.8.6 + '@temporalio/client': + specifier: ~1.8.6 + version: 1.8.6 + '@temporalio/workflow': + specifier: ~1.8.6 + version: 1.8.6 + axios: + specifier: ~1.5.1 + version: 1.5.1 + moment: + specifier: ~2.29.4 + version: 2.29.4 + ts-node: + specifier: ^10.9.1 + version: 10.9.1(@swc/core@1.3.100)(@types/node@20.10.1)(typescript@5.3.2) + tsconfig-paths: + specifier: ^4.2.0 + version: 4.2.0 + typescript: + specifier: ^5.2.2 + version: 5.3.2 + uuid: + specifier: ~9.0.1 + version: 9.0.1 + devDependencies: + '@types/node': + specifier: ^20.8.2 + version: 20.10.1 + '@types/uuid': + specifier: ~9.0.6 + version: 9.0.7 + '@typescript-eslint/eslint-plugin': + specifier: ^6.7.4 + version: 6.13.1(@typescript-eslint/parser@6.13.1)(eslint@8.54.0)(typescript@5.3.2) + '@typescript-eslint/parser': + specifier: ^6.7.4 + version: 6.13.1(eslint@8.54.0)(typescript@5.3.2) + eslint: + specifier: ^8.50.0 + version: 8.54.0 + eslint-config-prettier: + specifier: ^9.0.0 + version: 9.0.0(eslint@8.54.0) + eslint-plugin-prettier: + specifier: ^5.0.0 + version: 5.0.1(eslint-config-prettier@9.0.0)(eslint@8.54.0)(prettier@3.1.0) + nodemon: + specifier: ^3.0.1 + version: 3.0.1 + prettier: + specifier: ^3.0.3 + version: 3.1.0 + services/apps/data_sink_worker: dependencies: '@crowd/alerting': @@ -478,6 +603,9 @@ importers: '@crowd/common': specifier: file:../../libs/common version: file:services/libs/common + '@crowd/common_services': + specifier: file:../../libs/common_services + version: file:services/libs/common_services '@crowd/conversations': specifier: file:../../libs/conversations version: file:services/libs/conversations @@ -535,6 +663,12 @@ importers: lodash.uniqby: specifier: ^4.7.0 version: 4.7.0 + moment: + specifier: 2.29.4 + version: 2.29.4 + moment-timezone: + specifier: ^0.5.34 + version: 0.5.43 ts-node: specifier: ^10.9.1 version: 10.9.1(@types/node@18.18.14)(typescript@5.3.2) @@ -580,13 +714,98 @@ importers: version: file:services/libs/common '@crowd/cubejs': specifier: file:../../libs/cubejs - version: file:services/libs/cubejs(bufferutil@4.0.8)(utf-8-validate@5.0.10) + version: file:services/libs/cubejs '@crowd/types': specifier: file:../../libs/types version: file:services/libs/types '@sendgrid/mail': - specifier: ~7.7.0 - version: 7.7.0 + specifier: ~8.1.0 + version: 8.1.0 + '@temporalio/activity': + specifier: ~1.8.6 + version: 1.8.6 + '@temporalio/client': + specifier: ~1.8.6 + version: 1.8.6 + '@temporalio/workflow': + specifier: ~1.8.6 + version: 1.8.6 + axios: + specifier: ~1.5.1 + version: 1.5.1 + html-to-text: + specifier: ~9.0.5 + version: 9.0.5 + lodash: + specifier: ~4.17.21 + version: 4.17.21 + moment: + specifier: ~2.29.4 + version: 2.29.4 + ts-node: + specifier: ^10.9.1 + version: 10.9.1(@swc/core@1.3.100)(@types/node@20.10.1)(typescript@5.3.2) + tsconfig-paths: + specifier: ^4.2.0 + version: 4.2.0 + typescript: + specifier: ^5.2.2 + version: 5.3.2 + uuid: + specifier: ~9.0.1 + version: 9.0.1 + devDependencies: + '@types/node': + specifier: ^20.8.2 + version: 20.10.1 + '@types/uuid': + specifier: ~9.0.6 + version: 9.0.7 + '@typescript-eslint/eslint-plugin': + specifier: ^6.7.4 + version: 6.13.1(@typescript-eslint/parser@6.13.1)(eslint@8.54.0)(typescript@5.3.2) + '@typescript-eslint/parser': + specifier: ^6.7.4 + version: 6.13.1(eslint@8.54.0)(typescript@5.3.2) + eslint: + specifier: ^8.50.0 + version: 8.54.0 + eslint-config-prettier: + specifier: ^9.0.0 + version: 9.0.0(eslint@8.54.0) + eslint-plugin-prettier: + specifier: ^5.0.0 + version: 5.0.1(eslint-config-prettier@9.0.0)(eslint@8.54.0)(prettier@3.1.0) + nodemon: + specifier: ^3.0.1 + version: 3.0.1 + prettier: + specifier: ^3.0.3 + version: 3.1.0 + + services/apps/entity_merging_worker: + dependencies: + '@crowd/archetype-standard': + specifier: file:../../archetypes/standard + version: file:services/archetypes/standard(@swc/core@1.3.100)(@types/node@20.10.1)(typescript@5.3.2) + '@crowd/archetype-worker': + specifier: file:../../archetypes/worker + version: file:services/archetypes/worker(@swc/core@1.3.100)(@types/node@20.10.1)(typescript@5.3.2) + '@crowd/common': + specifier: file:../../libs/common + version: file:services/libs/common + '@crowd/feature-flags': + specifier: file:../../libs/feature-flags + version: file:services/libs/feature-flags + '@crowd/redis': + specifier: file:../../libs/redis + version: file:services/libs/redis + '@crowd/types': + specifier: file:../../libs/types + version: file:services/libs/types + '@sendgrid/mail': + specifier: ~8.1.0 + version: 8.1.0 '@temporalio/activity': specifier: ~1.8.6 version: 1.8.6 @@ -608,6 +827,9 @@ importers: moment: specifier: ~2.29.4 version: 2.29.4 + moment-timezone: + specifier: ^0.5.34 + version: 0.5.43 ts-node: specifier: ^10.9.1 version: 10.9.1(@swc/core@1.3.100)(@types/node@20.10.1)(typescript@5.3.2) @@ -657,9 +879,15 @@ importers: '@crowd/common': specifier: file:../../libs/common version: file:services/libs/common + '@crowd/common_services': + specifier: file:../../libs/common_services + version: file:services/libs/common_services '@crowd/database': specifier: file:../../libs/database version: file:services/libs/database + '@crowd/feature-flags': + specifier: file:../../libs/feature-flags + version: file:services/libs/feature-flags '@crowd/integrations': specifier: file:../../libs/integrations version: file:services/libs/integrations @@ -730,9 +958,15 @@ importers: '@crowd/common': specifier: file:../../libs/common version: file:services/libs/common + '@crowd/common_services': + specifier: file:../../libs/common_services + version: file:services/libs/common_services '@crowd/database': specifier: file:../../libs/database version: file:services/libs/database + '@crowd/feature-flags': + specifier: file:../../libs/feature-flags + version: file:services/libs/feature-flags '@crowd/integrations': specifier: file:../../libs/integrations version: file:services/libs/integrations @@ -774,172 +1008,464 @@ importers: version: 9.0.1 devDependencies: '@typescript-eslint/eslint-plugin': - specifier: ^5.59.2 - version: 5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.54.0)(typescript@5.3.2) + specifier: ^5.59.2 + version: 5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.54.0)(typescript@5.3.2) + '@typescript-eslint/parser': + specifier: ^5.59.2 + version: 5.62.0(eslint@8.54.0)(typescript@5.3.2) + concurrently: + specifier: ^8.0.1 + version: 8.2.2 + eslint: + specifier: ^8.39.0 + version: 8.54.0 + eslint-config-prettier: + specifier: ^8.8.0 + version: 8.10.0(eslint@8.54.0) + eslint-plugin-prettier: + specifier: ^4.2.1 + version: 4.2.1(eslint-config-prettier@8.10.0)(eslint@8.54.0)(prettier@2.8.8) + nodemon: + specifier: ^2.0.22 + version: 2.0.22 + prettier: + specifier: ^2.8.8 + version: 2.8.8 + + services/apps/integration_stream_worker: + dependencies: + '@crowd/common': + specifier: file:../../libs/common + version: file:services/libs/common + '@crowd/common_services': + specifier: file:../../libs/common_services + version: file:services/libs/common_services + '@crowd/database': + specifier: file:../../libs/database + version: file:services/libs/database + '@crowd/feature-flags': + specifier: file:../../libs/feature-flags + version: file:services/libs/feature-flags + '@crowd/integrations': + specifier: file:../../libs/integrations + version: file:services/libs/integrations + '@crowd/logging': + specifier: file:../../libs/logging + version: file:services/libs/logging + '@crowd/redis': + specifier: file:../../libs/redis + version: file:services/libs/redis + '@crowd/sqs': + specifier: file:../../libs/sqs + version: file:services/libs/sqs + '@crowd/tracing': + specifier: file:../../libs/tracing + version: file:services/libs/tracing + '@crowd/types': + specifier: file:../../libs/types + version: file:services/libs/types + '@types/config': + specifier: ^3.3.0 + version: 3.3.3 + '@types/node': + specifier: ^18.16.3 + version: 18.18.14 + config: + specifier: ^3.3.9 + version: 3.3.9 + ts-node: + specifier: ^10.9.1 + version: 10.9.1(@types/node@18.18.14)(typescript@5.3.2) + tsconfig-paths: + specifier: ^4.2.0 + version: 4.2.0 + typescript: + specifier: ^5.0.4 + version: 5.3.2 + uuid: + specifier: ^9.0.0 + version: 9.0.1 + devDependencies: + '@typescript-eslint/eslint-plugin': + specifier: ^5.59.2 + version: 5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.54.0)(typescript@5.3.2) + '@typescript-eslint/parser': + specifier: ^5.59.2 + version: 5.62.0(eslint@8.54.0)(typescript@5.3.2) + eslint: + specifier: ^8.39.0 + version: 8.54.0 + eslint-config-prettier: + specifier: ^8.8.0 + version: 8.10.0(eslint@8.54.0) + eslint-plugin-prettier: + specifier: ^4.2.1 + version: 4.2.1(eslint-config-prettier@8.10.0)(eslint@8.54.0)(prettier@2.8.8) + nodemon: + specifier: ^2.0.22 + version: 2.0.22 + prettier: + specifier: ^2.8.8 + version: 2.8.8 + + services/apps/integration_sync_worker: + dependencies: + '@crowd/common': + specifier: file:../../libs/common + version: file:services/libs/common + '@crowd/database': + specifier: file:../../libs/database + version: file:services/libs/database + '@crowd/integrations': + specifier: file:../../libs/integrations + version: file:services/libs/integrations + '@crowd/logging': + specifier: file:../../libs/logging + version: file:services/libs/logging + '@crowd/opensearch': + specifier: file:../../libs/opensearch + version: file:services/libs/opensearch + '@crowd/sqs': + specifier: file:../../libs/sqs + version: file:services/libs/sqs + '@crowd/tracing': + specifier: file:../../libs/tracing + version: file:services/libs/tracing + '@crowd/types': + specifier: file:../../libs/types + version: file:services/libs/types + '@opensearch-project/opensearch': + specifier: ^1.2.0 + version: 1.2.0 + '@types/config': + specifier: ^3.3.0 + version: 3.3.3 + '@types/node': + specifier: ^18.16.3 + version: 18.18.14 + config: + specifier: ^3.3.9 + version: 3.3.9 + ts-node: + specifier: ^10.9.1 + version: 10.9.1(@types/node@18.18.14)(typescript@5.3.2) + tsconfig-paths: + specifier: ^4.2.0 + version: 4.2.0 + typescript: + specifier: ^5.0.4 + version: 5.3.2 + devDependencies: + '@typescript-eslint/eslint-plugin': + specifier: ^5.59.2 + version: 5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.54.0)(typescript@5.3.2) + '@typescript-eslint/parser': + specifier: ^5.59.2 + version: 5.62.0(eslint@8.54.0)(typescript@5.3.2) + eslint: + specifier: ^8.39.0 + version: 8.54.0 + eslint-config-prettier: + specifier: ^8.8.0 + version: 8.10.0(eslint@8.54.0) + eslint-plugin-prettier: + specifier: ^4.2.1 + version: 4.2.1(eslint-config-prettier@8.10.0)(eslint@8.54.0)(prettier@2.8.8) + nodemon: + specifier: ^2.0.22 + version: 2.0.22 + prettier: + specifier: ^2.8.8 + version: 2.8.8 + + services/apps/merge_suggestions_worker: + dependencies: + '@crowd/archetype-standard': + specifier: file:../../archetypes/standard + version: file:services/archetypes/standard(@swc/core@1.3.100)(@types/node@20.10.1)(typescript@5.3.2) + '@crowd/archetype-worker': + specifier: file:../../archetypes/worker + version: file:services/archetypes/worker(@swc/core@1.3.100)(@types/node@20.10.1)(typescript@5.3.2) + '@crowd/common': + specifier: file:../../libs/common + version: file:services/libs/common + '@crowd/cubejs': + specifier: file:../../libs/cubejs + version: file:services/libs/cubejs + '@crowd/feature-flags': + specifier: file:../../libs/feature-flags + version: file:services/libs/feature-flags + '@crowd/types': + specifier: file:../../libs/types + version: file:services/libs/types + '@sendgrid/mail': + specifier: ~8.1.0 + version: 8.1.0 + '@temporalio/activity': + specifier: ~1.8.6 + version: 1.8.6 + '@temporalio/client': + specifier: ~1.8.6 + version: 1.8.6 + '@temporalio/workflow': + specifier: ~1.8.6 + version: 1.8.6 + axios: + specifier: ~1.5.1 + version: 1.5.1 + fast-levenshtein: + specifier: ^3.0.0 + version: 3.0.0 + html-to-text: + specifier: ~9.0.5 + version: 9.0.5 + lodash: + specifier: ~4.17.21 + version: 4.17.21 + moment: + specifier: ~2.29.4 + version: 2.29.4 + ts-node: + specifier: ^10.9.1 + version: 10.9.1(@swc/core@1.3.100)(@types/node@20.10.1)(typescript@5.3.2) + tsconfig-paths: + specifier: ^4.2.0 + version: 4.2.0 + typescript: + specifier: ^5.2.2 + version: 5.3.2 + uuid: + specifier: ~9.0.1 + version: 9.0.1 + devDependencies: + '@types/node': + specifier: ^20.8.2 + version: 20.10.1 + '@types/uuid': + specifier: ~9.0.6 + version: 9.0.7 + '@typescript-eslint/eslint-plugin': + specifier: ^6.7.4 + version: 6.13.1(@typescript-eslint/parser@6.13.1)(eslint@8.54.0)(typescript@5.3.2) + '@typescript-eslint/parser': + specifier: ^6.7.4 + version: 6.13.1(eslint@8.54.0)(typescript@5.3.2) + eslint: + specifier: ^8.50.0 + version: 8.54.0 + eslint-config-prettier: + specifier: ^9.0.0 + version: 9.0.0(eslint@8.54.0) + eslint-plugin-prettier: + specifier: ^5.0.0 + version: 5.0.1(eslint-config-prettier@9.0.0)(eslint@8.54.0)(prettier@3.1.0) + nodemon: + specifier: ^3.0.1 + version: 3.0.1 + prettier: + specifier: ^3.0.3 + version: 3.1.0 + + services/apps/premium/members_enrichment_worker: + dependencies: + '@crowd/archetype-standard': + specifier: file:../../../archetypes/standard + version: file:services/archetypes/standard(@swc/core@1.3.100)(@types/node@20.10.1)(typescript@5.3.2) + '@crowd/archetype-worker': + specifier: file:../../../archetypes/worker + version: file:services/archetypes/worker(@swc/core@1.3.100)(@types/node@20.10.1)(typescript@5.3.2) + '@crowd/common': + specifier: file:../../../libs/common + version: file:services/libs/common + '@crowd/opensearch': + specifier: file:../../../libs/opensearch + version: file:services/libs/opensearch + '@crowd/types': + specifier: file:../../../libs/types + version: file:services/libs/types + '@temporalio/activity': + specifier: ~1.8.6 + version: 1.8.6 + '@temporalio/client': + specifier: ~1.8.6 + version: 1.8.6 + '@temporalio/workflow': + specifier: ~1.8.6 + version: 1.8.6 + axios: + specifier: ~1.6.2 + version: 1.6.2 + lodash: + specifier: ~4.17.21 + version: 4.17.21 + moment: + specifier: ~2.29.4 + version: 2.29.4 + ts-node: + specifier: ^10.9.1 + version: 10.9.1(@swc/core@1.3.100)(@types/node@20.10.1)(typescript@5.3.2) + tsconfig-paths: + specifier: ^4.2.0 + version: 4.2.0 + typescript: + specifier: ^5.2.2 + version: 5.3.2 + devDependencies: + '@types/node': + specifier: ^20.8.2 + version: 20.10.1 + '@types/uuid': + specifier: ~9.0.6 + version: 9.0.7 + '@typescript-eslint/eslint-plugin': + specifier: ^6.7.4 + version: 6.13.1(@typescript-eslint/parser@6.13.1)(eslint@8.54.0)(typescript@5.3.2) '@typescript-eslint/parser': - specifier: ^5.59.2 - version: 5.62.0(eslint@8.54.0)(typescript@5.3.2) - concurrently: - specifier: ^8.0.1 - version: 8.2.2 + specifier: ^6.7.4 + version: 6.13.1(eslint@8.54.0)(typescript@5.3.2) eslint: - specifier: ^8.39.0 + specifier: ^8.50.0 version: 8.54.0 eslint-config-prettier: - specifier: ^8.8.0 - version: 8.10.0(eslint@8.54.0) + specifier: ^9.0.0 + version: 9.0.0(eslint@8.54.0) eslint-plugin-prettier: - specifier: ^4.2.1 - version: 4.2.1(eslint-config-prettier@8.10.0)(eslint@8.54.0)(prettier@2.8.8) + specifier: ^5.0.0 + version: 5.0.1(eslint-config-prettier@9.0.0)(eslint@8.54.0)(prettier@3.1.0) nodemon: - specifier: ^2.0.22 - version: 2.0.22 + specifier: ^3.0.1 + version: 3.0.1 prettier: - specifier: ^2.8.8 - version: 2.8.8 + specifier: ^3.0.3 + version: 3.1.0 - services/apps/integration_stream_worker: + services/apps/premium/organizations_enrichment_worker: dependencies: + '@crowd/archetype-standard': + specifier: file:../../../archetypes/standard + version: file:services/archetypes/standard(@swc/core@1.3.100)(@types/node@20.10.1)(typescript@5.3.2) + '@crowd/archetype-worker': + specifier: file:../../../archetypes/worker + version: file:services/archetypes/worker(@swc/core@1.3.100)(@types/node@20.10.1)(typescript@5.3.2) '@crowd/common': - specifier: file:../../libs/common + specifier: file:../../../libs/common version: file:services/libs/common + '@crowd/common_services': + specifier: file:../../../libs/common_services + version: file:services/libs/common_services '@crowd/database': - specifier: file:../../libs/database + specifier: file:../../../libs/database version: file:services/libs/database - '@crowd/integrations': - specifier: file:../../libs/integrations - version: file:services/libs/integrations + '@crowd/feature-flags': + specifier: file:../../../libs/feature-flags + version: file:services/libs/feature-flags '@crowd/logging': - specifier: file:../../libs/logging + specifier: file:../../../libs/logging version: file:services/libs/logging '@crowd/redis': - specifier: file:../../libs/redis + specifier: file:../../../libs/redis version: file:services/libs/redis - '@crowd/sqs': - specifier: file:../../libs/sqs - version: file:services/libs/sqs - '@crowd/tracing': - specifier: file:../../libs/tracing - version: file:services/libs/tracing '@crowd/types': - specifier: file:../../libs/types + specifier: file:../../../libs/types version: file:services/libs/types - '@types/config': - specifier: ^3.3.0 - version: 3.3.3 - '@types/node': - specifier: ^18.16.3 - version: 18.18.14 - config: - specifier: ^3.3.9 - version: 3.3.9 + '@temporalio/client': + specifier: ~1.8.6 + version: 1.8.6 + '@temporalio/workflow': + specifier: ~1.8.6 + version: 1.8.6 + peopledatalabs: + specifier: ~6.1.5 + version: 6.1.5 ts-node: specifier: ^10.9.1 - version: 10.9.1(@types/node@18.18.14)(typescript@5.3.2) + version: 10.9.1(@swc/core@1.3.100)(@types/node@20.10.1)(typescript@5.3.2) tsconfig-paths: specifier: ^4.2.0 version: 4.2.0 typescript: - specifier: ^5.0.4 + specifier: ^5.2.2 version: 5.3.2 - uuid: - specifier: ^9.0.0 - version: 9.0.1 devDependencies: + '@types/node': + specifier: ^20.8.2 + version: 20.10.1 + '@types/uuid': + specifier: ~9.0.6 + version: 9.0.7 '@typescript-eslint/eslint-plugin': - specifier: ^5.59.2 - version: 5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.54.0)(typescript@5.3.2) + specifier: ^6.7.4 + version: 6.13.1(@typescript-eslint/parser@6.13.1)(eslint@8.54.0)(typescript@5.3.2) '@typescript-eslint/parser': - specifier: ^5.59.2 - version: 5.62.0(eslint@8.54.0)(typescript@5.3.2) + specifier: ^6.7.4 + version: 6.13.1(eslint@8.54.0)(typescript@5.3.2) eslint: - specifier: ^8.39.0 + specifier: ^8.50.0 version: 8.54.0 eslint-config-prettier: - specifier: ^8.8.0 - version: 8.10.0(eslint@8.54.0) + specifier: ^9.0.0 + version: 9.0.0(eslint@8.54.0) eslint-plugin-prettier: - specifier: ^4.2.1 - version: 4.2.1(eslint-config-prettier@8.10.0)(eslint@8.54.0)(prettier@2.8.8) + specifier: ^5.0.0 + version: 5.0.1(eslint-config-prettier@9.0.0)(eslint@8.54.0)(prettier@3.1.0) nodemon: - specifier: ^2.0.22 - version: 2.0.22 + specifier: ^3.0.1 + version: 3.0.1 prettier: - specifier: ^2.8.8 - version: 2.8.8 + specifier: ^3.0.3 + version: 3.1.0 - services/apps/integration_sync_worker: + services/apps/profiles_worker: dependencies: - '@crowd/common': - specifier: file:../../libs/common - version: file:services/libs/common - '@crowd/database': - specifier: file:../../libs/database - version: file:services/libs/database - '@crowd/integrations': - specifier: file:../../libs/integrations - version: file:services/libs/integrations - '@crowd/logging': - specifier: file:../../libs/logging - version: file:services/libs/logging - '@crowd/opensearch': - specifier: file:../../libs/opensearch - version: file:services/libs/opensearch - '@crowd/redis': - specifier: file:../../libs/redis - version: file:services/libs/redis - '@crowd/sqs': - specifier: file:../../libs/sqs - version: file:services/libs/sqs - '@crowd/tracing': - specifier: file:../../libs/tracing - version: file:services/libs/tracing + '@crowd/archetype-standard': + specifier: file:../../archetypes/standard + version: file:services/archetypes/standard(@swc/core@1.3.100)(@types/node@20.10.1)(typescript@5.3.2) + '@crowd/archetype-worker': + specifier: file:../../archetypes/worker + version: file:services/archetypes/worker(@swc/core@1.3.100)(@types/node@20.10.1)(typescript@5.3.2) '@crowd/types': specifier: file:../../libs/types version: file:services/libs/types - '@opensearch-project/opensearch': - specifier: ^1.2.0 - version: 1.2.0 - '@types/config': - specifier: ^3.3.0 - version: 3.3.3 - '@types/node': - specifier: ^18.16.3 - version: 18.18.14 - config: - specifier: ^3.3.9 - version: 3.3.9 + '@temporalio/workflow': + specifier: ~1.8.6 + version: 1.8.6 ts-node: specifier: ^10.9.1 - version: 10.9.1(@types/node@18.18.14)(typescript@5.3.2) + version: 10.9.1(@swc/core@1.3.100)(@types/node@20.10.1)(typescript@5.3.2) tsconfig-paths: specifier: ^4.2.0 version: 4.2.0 typescript: - specifier: ^5.0.4 + specifier: ^5.2.2 version: 5.3.2 devDependencies: + '@types/node': + specifier: ^20.8.2 + version: 20.10.1 + '@types/uuid': + specifier: ~9.0.6 + version: 9.0.7 '@typescript-eslint/eslint-plugin': - specifier: ^5.59.2 - version: 5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.54.0)(typescript@5.3.2) + specifier: ^6.7.4 + version: 6.13.1(@typescript-eslint/parser@6.13.1)(eslint@8.54.0)(typescript@5.3.2) '@typescript-eslint/parser': - specifier: ^5.59.2 - version: 5.62.0(eslint@8.54.0)(typescript@5.3.2) + specifier: ^6.7.4 + version: 6.13.1(eslint@8.54.0)(typescript@5.3.2) eslint: - specifier: ^8.39.0 + specifier: ^8.50.0 version: 8.54.0 eslint-config-prettier: - specifier: ^8.8.0 - version: 8.10.0(eslint@8.54.0) + specifier: ^9.0.0 + version: 9.0.0(eslint@8.54.0) eslint-plugin-prettier: - specifier: ^4.2.1 - version: 4.2.1(eslint-config-prettier@8.10.0)(eslint@8.54.0)(prettier@2.8.8) + specifier: ^5.0.0 + version: 5.0.1(eslint-config-prettier@9.0.0)(eslint@8.54.0)(prettier@3.1.0) nodemon: - specifier: ^2.0.22 - version: 2.0.22 + specifier: ^3.0.1 + version: 3.0.1 prettier: - specifier: ^2.8.8 - version: 2.8.8 + specifier: ^3.0.3 + version: 3.1.0 services/apps/search_sync_api: dependencies: @@ -1239,12 +1765,21 @@ importers: '@crowd/common': specifier: file:../../libs/common version: file:services/libs/common + '@crowd/common_services': + specifier: file:../../libs/common_services + version: file:services/libs/common_services '@crowd/database': specifier: file:../../libs/database version: file:services/libs/database + '@crowd/feature-flags': + specifier: file:../../libs/feature-flags + version: file:services/libs/feature-flags '@crowd/logging': specifier: file:../../libs/logging version: file:services/libs/logging + '@crowd/redis': + specifier: file:../../libs/redis + version: file:services/libs/redis '@crowd/sqs': specifier: file:../../libs/sqs version: file:services/libs/sqs @@ -1431,12 +1966,21 @@ importers: '@crowd/archetype-standard': specifier: file:../../archetypes/standard version: file:services/archetypes/standard(@swc/core@1.3.100)(@types/node@20.10.1)(typescript@5.3.2) + '@crowd/common': + specifier: file:../../libs/common + version: file:services/libs/common '@crowd/database': specifier: file:../../libs/database version: file:services/libs/database + '@crowd/sqs': + specifier: file:../../libs/sqs + version: file:services/libs/sqs '@crowd/temporal': specifier: file:../../libs/temporal version: file:services/libs/temporal + '@opensearch-project/opensearch': + specifier: ^1.2.0 + version: 1.2.0 '@temporalio/client': specifier: ~1.8.6 version: 1.8.6 @@ -1557,6 +2101,58 @@ importers: specifier: ^5.0.4 version: 5.3.2 + services/libs/common_services: + dependencies: + '@crowd/common': + specifier: file:../common + version: file:services/libs/common + '@crowd/database': + specifier: file:../database + version: file:services/libs/database + '@crowd/feature-flags': + specifier: file:../feature-flags + version: file:services/libs/feature-flags + '@crowd/logging': + specifier: file:../logging + version: file:services/libs/logging + '@crowd/redis': + specifier: file:../redis + version: file:services/libs/redis + '@crowd/sqs': + specifier: file:../sqs + version: file:services/libs/sqs + '@crowd/tracing': + specifier: file:../tracing + version: file:services/libs/tracing + '@crowd/types': + specifier: file:../types + version: file:services/libs/types + devDependencies: + '@types/node': + specifier: ^18.16.3 + version: 18.18.14 + '@typescript-eslint/eslint-plugin': + specifier: ^5.59.2 + version: 5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.54.0)(typescript@5.3.2) + '@typescript-eslint/parser': + specifier: ^5.59.2 + version: 5.62.0(eslint@8.54.0)(typescript@5.3.2) + eslint: + specifier: ^8.39.0 + version: 8.54.0 + eslint-config-prettier: + specifier: ^8.8.0 + version: 8.10.0(eslint@8.54.0) + eslint-plugin-prettier: + specifier: ^4.2.1 + version: 4.2.1(eslint-config-prettier@8.10.0)(eslint@8.54.0)(prettier@2.8.8) + prettier: + specifier: ^2.8.8 + version: 2.8.8 + typescript: + specifier: ^5.0.4 + version: 5.3.2 + services/libs/conversations: dependencies: '@crowd/common': @@ -1611,9 +2207,6 @@ importers: '@crowd/logging': specifier: file:../logging version: file:services/libs/logging - '@cubejs-backend/server-core': - specifier: ^0.32.27 - version: 0.32.31(bufferutil@4.0.8)(utf-8-validate@5.0.10) '@cubejs-client/core': specifier: ~0.34.9 version: 0.34.27 @@ -2165,6 +2758,10 @@ importers: version: 5.3.2 services/libs/types: + dependencies: + peopledatalabs: + specifier: ~6.1.5 + version: 6.1.5 devDependencies: '@types/node': specifier: ^18.16.3 @@ -2202,14 +2799,22 @@ packages: dependencies: '@actions/http-client': 2.2.0 uuid: 8.3.2 - dev: true + + /@actions/exec@1.1.1: + resolution: {integrity: sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==} + dependencies: + '@actions/io': 1.1.3 + dev: false /@actions/http-client@2.2.0: resolution: {integrity: sha512-q+epW0trjVUUHboliPb4UF9g2msf+w61b32tAkFEwL/IwP0DQWgbCMM0Hbe3e3WXSKz5VcUXbzJQgy8Hkra/Lg==} dependencies: tunnel: 0.0.6 undici: 5.28.1 - dev: true + + /@actions/io@1.1.3: + resolution: {integrity: sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==} + dev: false /@ampproject/remapping@2.2.1: resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==} @@ -2217,6 +2822,7 @@ packages: dependencies: '@jridgewell/gen-mapping': 0.3.3 '@jridgewell/trace-mapping': 0.3.20 + dev: true /@apidevtools/openapi-schemas@2.1.0: resolution: {integrity: sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ==} @@ -2830,10 +3436,12 @@ packages: dependencies: '@babel/highlight': 7.23.4 chalk: 2.4.2 + dev: true /@babel/compat-data@7.23.5: resolution: {integrity: sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==} engines: {node: '>=6.9.0'} + dev: true /@babel/core@7.23.5: resolution: {integrity: sha512-Cwc2XjUrG4ilcfOw4wBAK+enbdgwAcAJCfGUItPBKR7Mjw4aEfAFYrLxeRp4jWgtNIKn3n2AlBOfwwafl+42/g==} @@ -2856,6 +3464,7 @@ packages: semver: 6.3.1 transitivePeerDependencies: - supports-color + dev: true /@babel/generator@7.23.5: resolution: {integrity: sha512-BPssCHrBD+0YrxviOa3QzpqwhNIXKEtOa2jQrm4FlmkC2apYgRnQcmPWiGZDlGxiNtltnUFolMe8497Esry+jA==} @@ -2865,18 +3474,21 @@ packages: '@jridgewell/gen-mapping': 0.3.3 '@jridgewell/trace-mapping': 0.3.20 jsesc: 2.5.2 + dev: true /@babel/helper-annotate-as-pure@7.22.5: resolution: {integrity: sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==} engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.23.5 + dev: true /@babel/helper-builder-binary-assignment-operator-visitor@7.22.15: resolution: {integrity: sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==} engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.23.5 + dev: true /@babel/helper-compilation-targets@7.22.15: resolution: {integrity: sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==} @@ -2887,6 +3499,7 @@ packages: browserslist: 4.22.1 lru-cache: 5.1.1 semver: 6.3.1 + dev: true /@babel/helper-create-class-features-plugin@7.23.5(@babel/core@7.23.5): resolution: {integrity: sha512-QELlRWxSpgdwdJzSJn4WAhKC+hvw/AtHbbrIoncKHkhKKR/luAlKkgBDcri1EzWAo8f8VvYVryEHN4tax/V67A==} @@ -2904,6 +3517,7 @@ packages: '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 '@babel/helper-split-export-declaration': 7.22.6 semver: 6.3.1 + dev: true /@babel/helper-create-regexp-features-plugin@7.22.15(@babel/core@7.23.5): resolution: {integrity: sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==} @@ -2915,6 +3529,7 @@ packages: '@babel/helper-annotate-as-pure': 7.22.5 regexpu-core: 5.3.2 semver: 6.3.1 + dev: true /@babel/helper-define-polyfill-provider@0.4.3(@babel/core@7.23.5): resolution: {integrity: sha512-WBrLmuPP47n7PNwsZ57pqam6G/RGo1vw/87b0Blc53tZNGZ4x7YvZ6HgQe2vo1W/FR20OgjeZuGXzudPiXHFug==} @@ -2929,10 +3544,12 @@ packages: resolve: 1.22.8 transitivePeerDependencies: - supports-color + dev: true /@babel/helper-environment-visitor@7.22.20: resolution: {integrity: sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==} engines: {node: '>=6.9.0'} + dev: true /@babel/helper-function-name@7.23.0: resolution: {integrity: sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==} @@ -2940,24 +3557,28 @@ packages: dependencies: '@babel/template': 7.22.15 '@babel/types': 7.23.5 + dev: true /@babel/helper-hoist-variables@7.22.5: resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==} engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.23.5 + dev: true /@babel/helper-member-expression-to-functions@7.23.0: resolution: {integrity: sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==} engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.23.5 + dev: true /@babel/helper-module-imports@7.22.15: resolution: {integrity: sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==} engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.23.5 + dev: true /@babel/helper-module-transforms@7.23.3(@babel/core@7.23.5): resolution: {integrity: sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==} @@ -2971,16 +3592,19 @@ packages: '@babel/helper-simple-access': 7.22.5 '@babel/helper-split-export-declaration': 7.22.6 '@babel/helper-validator-identifier': 7.22.20 + dev: true /@babel/helper-optimise-call-expression@7.22.5: resolution: {integrity: sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==} engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.23.5 + dev: true /@babel/helper-plugin-utils@7.22.5: resolution: {integrity: sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==} engines: {node: '>=6.9.0'} + dev: true /@babel/helper-remap-async-to-generator@7.22.20(@babel/core@7.23.5): resolution: {integrity: sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==} @@ -2992,6 +3616,7 @@ packages: '@babel/helper-annotate-as-pure': 7.22.5 '@babel/helper-environment-visitor': 7.22.20 '@babel/helper-wrap-function': 7.22.20 + dev: true /@babel/helper-replace-supers@7.22.20(@babel/core@7.23.5): resolution: {integrity: sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==} @@ -3003,36 +3628,43 @@ packages: '@babel/helper-environment-visitor': 7.22.20 '@babel/helper-member-expression-to-functions': 7.23.0 '@babel/helper-optimise-call-expression': 7.22.5 + dev: true /@babel/helper-simple-access@7.22.5: resolution: {integrity: sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==} engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.23.5 + dev: true /@babel/helper-skip-transparent-expression-wrappers@7.22.5: resolution: {integrity: sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==} engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.23.5 + dev: true /@babel/helper-split-export-declaration@7.22.6: resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==} engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.23.5 + dev: true /@babel/helper-string-parser@7.23.4: resolution: {integrity: sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==} engines: {node: '>=6.9.0'} + dev: true /@babel/helper-validator-identifier@7.22.20: resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} engines: {node: '>=6.9.0'} + dev: true /@babel/helper-validator-option@7.23.5: resolution: {integrity: sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==} engines: {node: '>=6.9.0'} + dev: true /@babel/helper-wrap-function@7.22.20: resolution: {integrity: sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==} @@ -3041,6 +3673,7 @@ packages: '@babel/helper-function-name': 7.23.0 '@babel/template': 7.22.15 '@babel/types': 7.23.5 + dev: true /@babel/helpers@7.23.5: resolution: {integrity: sha512-oO7us8FzTEsG3U6ag9MfdF1iA/7Z6dz+MtFhifZk8C8o453rGJFFWUP1t+ULM9TUIAzC9uxXEiXjOiVMyd7QPg==} @@ -3051,6 +3684,7 @@ packages: '@babel/types': 7.23.5 transitivePeerDependencies: - supports-color + dev: true /@babel/highlight@7.23.4: resolution: {integrity: sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==} @@ -3059,6 +3693,7 @@ packages: '@babel/helper-validator-identifier': 7.22.20 chalk: 2.4.2 js-tokens: 4.0.0 + dev: true /@babel/parser@7.23.5: resolution: {integrity: sha512-hOOqoiNXrmGdFbhgCzu6GiURxUgM27Xwd/aPuu8RfHEZPBzL1Z54okAHAQjXfcQNwvrlkAmAp4SlRTZ45vlthQ==} @@ -3066,6 +3701,7 @@ packages: hasBin: true dependencies: '@babel/types': 7.23.5 + dev: true /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.23.3(@babel/core@7.23.5): resolution: {integrity: sha512-iRkKcCqb7iGnq9+3G6rZ+Ciz5VywC4XNRHe57lKM+jOeYAoR0lVqdeeDRfh0tQcTfw/+vBhHn926FmQhLtlFLQ==} @@ -3075,6 +3711,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.23.3(@babel/core@7.23.5): resolution: {integrity: sha512-WwlxbfMNdVEpQjZmK5mhm7oSwD3dS6eU+Iwsi4Knl9wAletWem7kaRsGOG+8UEbRyqxY4SS5zvtfXwX+jMxUwQ==} @@ -3086,6 +3723,7 @@ packages: '@babel/helper-plugin-utils': 7.22.5 '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 '@babel/plugin-transform-optional-chaining': 7.23.4(@babel/core@7.23.5) + dev: true /@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.23.3(@babel/core@7.23.5): resolution: {integrity: sha512-XaJak1qcityzrX0/IU5nKHb34VaibwP3saKqG6a/tppelgllOH13LUann4ZCIBcVOeE6H18K4Vx9QKkVww3z/w==} @@ -3096,6 +3734,7 @@ packages: '@babel/core': 7.23.5 '@babel/helper-environment-visitor': 7.22.20 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.23.5): resolution: {integrity: sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==} @@ -3104,6 +3743,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.23.5 + dev: true /@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.23.5): resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} @@ -3112,6 +3752,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.23.5): resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} @@ -3129,6 +3770,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.23.5): resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} @@ -3138,6 +3780,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.23.5): resolution: {integrity: sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==} @@ -3146,6 +3789,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-syntax-export-namespace-from@7.8.3(@babel/core@7.23.5): resolution: {integrity: sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==} @@ -3154,6 +3798,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-syntax-import-assertions@7.23.3(@babel/core@7.23.5): resolution: {integrity: sha512-lPgDSU+SJLK3xmFDTV2ZRQAiM7UuUjGidwBywFavObCiZc1BeAAcMtHJKUya92hPHO+at63JJPLygilZard8jw==} @@ -3163,6 +3808,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-syntax-import-attributes@7.23.3(@babel/core@7.23.5): resolution: {integrity: sha512-pawnE0P9g10xgoP7yKr6CK63K2FMsTE+FZidZO/1PwRdzmAPVs+HS1mAURUsgaoxammTJvULUdIkEK0gOcU2tA==} @@ -3172,6 +3818,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.23.5): resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} @@ -3180,6 +3827,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.23.5): resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} @@ -3188,6 +3836,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-syntax-jsx@7.23.3(@babel/core@7.23.5): resolution: {integrity: sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg==} @@ -3206,6 +3855,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.23.5): resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} @@ -3214,6 +3864,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.23.5): resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} @@ -3222,6 +3873,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.23.5): resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} @@ -3230,6 +3882,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.23.5): resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} @@ -3238,6 +3891,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.23.5): resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} @@ -3246,6 +3900,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.23.5): resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} @@ -3255,6 +3910,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.23.5): resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} @@ -3264,6 +3920,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-syntax-typescript@7.23.3(@babel/core@7.23.5): resolution: {integrity: sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ==} @@ -3284,6 +3941,7 @@ packages: '@babel/core': 7.23.5 '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.23.5) '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-arrow-functions@7.23.3(@babel/core@7.23.5): resolution: {integrity: sha512-NzQcQrzaQPkaEwoTm4Mhyl8jI1huEL/WWIEvudjTCMJ9aBZNpsJbMASx7EQECtQQPS/DcnFpo0FIh3LvEO9cxQ==} @@ -3293,6 +3951,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-async-generator-functions@7.23.4(@babel/core@7.23.5): resolution: {integrity: sha512-efdkfPhHYTtn0G6n2ddrESE91fgXxjlqLsnUtPWnJs4a4mZIbUaK7ffqKIIUKXSHwcDvaCVX6GXkaJJFqtX7jw==} @@ -3305,6 +3964,7 @@ packages: '@babel/helper-plugin-utils': 7.22.5 '@babel/helper-remap-async-to-generator': 7.22.20(@babel/core@7.23.5) '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.23.5) + dev: true /@babel/plugin-transform-async-to-generator@7.23.3(@babel/core@7.23.5): resolution: {integrity: sha512-A7LFsKi4U4fomjqXJlZg/u0ft/n8/7n7lpffUP/ZULx/DtV9SGlNKZolHH6PE8Xl1ngCc0M11OaeZptXVkfKSw==} @@ -3316,6 +3976,7 @@ packages: '@babel/helper-module-imports': 7.22.15 '@babel/helper-plugin-utils': 7.22.5 '@babel/helper-remap-async-to-generator': 7.22.20(@babel/core@7.23.5) + dev: true /@babel/plugin-transform-block-scoped-functions@7.23.3(@babel/core@7.23.5): resolution: {integrity: sha512-vI+0sIaPIO6CNuM9Kk5VmXcMVRiOpDh7w2zZt9GXzmE/9KD70CUEVhvPR/etAeNK/FAEkhxQtXOzVF3EuRL41A==} @@ -3325,6 +3986,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-block-scoping@7.23.4(@babel/core@7.23.5): resolution: {integrity: sha512-0QqbP6B6HOh7/8iNR4CQU2Th/bbRtBp4KS9vcaZd1fZ0wSh5Fyssg0UCIHwxh+ka+pNDREbVLQnHCMHKZfPwfw==} @@ -3334,6 +3996,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-class-properties@7.23.3(@babel/core@7.23.5): resolution: {integrity: sha512-uM+AN8yCIjDPccsKGlw271xjJtGii+xQIF/uMPS8H15L12jZTsLfF4o5vNO7d/oUguOyfdikHGc/yi9ge4SGIg==} @@ -3344,6 +4007,7 @@ packages: '@babel/core': 7.23.5 '@babel/helper-create-class-features-plugin': 7.23.5(@babel/core@7.23.5) '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-class-static-block@7.23.4(@babel/core@7.23.5): resolution: {integrity: sha512-nsWu/1M+ggti1SOALj3hfx5FXzAY06fwPJsUZD4/A5e1bWi46VUIWtD+kOX6/IdhXGsXBWllLFDSnqSCdUNydQ==} @@ -3355,6 +4019,7 @@ packages: '@babel/helper-create-class-features-plugin': 7.23.5(@babel/core@7.23.5) '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.23.5) + dev: true /@babel/plugin-transform-classes@7.23.5(@babel/core@7.23.5): resolution: {integrity: sha512-jvOTR4nicqYC9yzOHIhXG5emiFEOpappSJAl73SDSEDcybD+Puuze8Tnpb9p9qEyYup24tq891gkaygIFvWDqg==} @@ -3372,6 +4037,7 @@ packages: '@babel/helper-replace-supers': 7.22.20(@babel/core@7.23.5) '@babel/helper-split-export-declaration': 7.22.6 globals: 11.12.0 + dev: true /@babel/plugin-transform-computed-properties@7.23.3(@babel/core@7.23.5): resolution: {integrity: sha512-dTj83UVTLw/+nbiHqQSFdwO9CbTtwq1DsDqm3CUEtDrZNET5rT5E6bIdTlOftDTDLMYxvxHNEYO4B9SLl8SLZw==} @@ -3382,6 +4048,7 @@ packages: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 '@babel/template': 7.22.15 + dev: true /@babel/plugin-transform-destructuring@7.23.3(@babel/core@7.23.5): resolution: {integrity: sha512-n225npDqjDIr967cMScVKHXJs7rout1q+tt50inyBCPkyZ8KxeI6d+GIbSBTT/w/9WdlWDOej3V9HE5Lgk57gw==} @@ -3391,6 +4058,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-dotall-regex@7.23.3(@babel/core@7.23.5): resolution: {integrity: sha512-vgnFYDHAKzFaTVp+mneDsIEbnJ2Np/9ng9iviHw3P/KVcgONxpNULEW/51Z/BaFojG2GI2GwwXck5uV1+1NOYQ==} @@ -3401,6 +4069,7 @@ packages: '@babel/core': 7.23.5 '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.23.5) '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-duplicate-keys@7.23.3(@babel/core@7.23.5): resolution: {integrity: sha512-RrqQ+BQmU3Oyav3J+7/myfvRCq7Tbz+kKLLshUmMwNlDHExbGL7ARhajvoBJEvc+fCguPPu887N+3RRXBVKZUA==} @@ -3410,6 +4079,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-dynamic-import@7.23.4(@babel/core@7.23.5): resolution: {integrity: sha512-V6jIbLhdJK86MaLh4Jpghi8ho5fGzt3imHOBu/x0jlBaPYqDoWz4RDXjmMOfnh+JWNaQleEAByZLV0QzBT4YQQ==} @@ -3420,6 +4090,7 @@ packages: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.23.5) + dev: true /@babel/plugin-transform-exponentiation-operator@7.23.3(@babel/core@7.23.5): resolution: {integrity: sha512-5fhCsl1odX96u7ILKHBj4/Y8vipoqwsJMh4csSA8qFfxrZDEA4Ssku2DyNvMJSmZNOEBT750LfFPbtrnTP90BQ==} @@ -3430,6 +4101,7 @@ packages: '@babel/core': 7.23.5 '@babel/helper-builder-binary-assignment-operator-visitor': 7.22.15 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-export-namespace-from@7.23.4(@babel/core@7.23.5): resolution: {integrity: sha512-GzuSBcKkx62dGzZI1WVgTWvkkz84FZO5TC5T8dl/Tht/rAla6Dg/Mz9Yhypg+ezVACf/rgDuQt3kbWEv7LdUDQ==} @@ -3440,6 +4112,7 @@ packages: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.23.5) + dev: true /@babel/plugin-transform-for-of@7.23.3(@babel/core@7.23.5): resolution: {integrity: sha512-X8jSm8X1CMwxmK878qsUGJRmbysKNbdpTv/O1/v0LuY/ZkZrng5WYiekYSdg9m09OTmDDUWeEDsTE+17WYbAZw==} @@ -3449,6 +4122,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-function-name@7.23.3(@babel/core@7.23.5): resolution: {integrity: sha512-I1QXp1LxIvt8yLaib49dRW5Okt7Q4oaxao6tFVKS/anCdEOMtYwWVKoiOA1p34GOWIZjUK0E+zCp7+l1pfQyiw==} @@ -3460,6 +4134,7 @@ packages: '@babel/helper-compilation-targets': 7.22.15 '@babel/helper-function-name': 7.23.0 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-json-strings@7.23.4(@babel/core@7.23.5): resolution: {integrity: sha512-81nTOqM1dMwZ/aRXQ59zVubN9wHGqk6UtqRK+/q+ciXmRy8fSolhGVvG09HHRGo4l6fr/c4ZhXUQH0uFW7PZbg==} @@ -3470,6 +4145,7 @@ packages: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.23.5) + dev: true /@babel/plugin-transform-literals@7.23.3(@babel/core@7.23.5): resolution: {integrity: sha512-wZ0PIXRxnwZvl9AYpqNUxpZ5BiTGrYt7kueGQ+N5FiQ7RCOD4cm8iShd6S6ggfVIWaJf2EMk8eRzAh52RfP4rQ==} @@ -3479,6 +4155,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-logical-assignment-operators@7.23.4(@babel/core@7.23.5): resolution: {integrity: sha512-Mc/ALf1rmZTP4JKKEhUwiORU+vcfarFVLfcFiolKUo6sewoxSEgl36ak5t+4WamRsNr6nzjZXQjM35WsU+9vbg==} @@ -3489,6 +4166,7 @@ packages: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.23.5) + dev: true /@babel/plugin-transform-member-expression-literals@7.23.3(@babel/core@7.23.5): resolution: {integrity: sha512-sC3LdDBDi5x96LA+Ytekz2ZPk8i/Ck+DEuDbRAll5rknJ5XRTSaPKEYwomLcs1AA8wg9b3KjIQRsnApj+q51Ag==} @@ -3498,6 +4176,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-modules-amd@7.23.3(@babel/core@7.23.5): resolution: {integrity: sha512-vJYQGxeKM4t8hYCKVBlZX/gtIY2I7mRGFNcm85sgXGMTBcoV3QdVtdpbcWEbzbfUIUZKwvgFT82mRvaQIebZzw==} @@ -3508,6 +4187,7 @@ packages: '@babel/core': 7.23.5 '@babel/helper-module-transforms': 7.23.3(@babel/core@7.23.5) '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-modules-commonjs@7.23.3(@babel/core@7.23.5): resolution: {integrity: sha512-aVS0F65LKsdNOtcz6FRCpE4OgsP2OFnW46qNxNIX9h3wuzaNcSQsJysuMwqSibC98HPrf2vCgtxKNwS0DAlgcA==} @@ -3519,6 +4199,7 @@ packages: '@babel/helper-module-transforms': 7.23.3(@babel/core@7.23.5) '@babel/helper-plugin-utils': 7.22.5 '@babel/helper-simple-access': 7.22.5 + dev: true /@babel/plugin-transform-modules-systemjs@7.23.3(@babel/core@7.23.5): resolution: {integrity: sha512-ZxyKGTkF9xT9YJuKQRo19ewf3pXpopuYQd8cDXqNzc3mUNbOME0RKMoZxviQk74hwzfQsEe66dE92MaZbdHKNQ==} @@ -3531,6 +4212,7 @@ packages: '@babel/helper-module-transforms': 7.23.3(@babel/core@7.23.5) '@babel/helper-plugin-utils': 7.22.5 '@babel/helper-validator-identifier': 7.22.20 + dev: true /@babel/plugin-transform-modules-umd@7.23.3(@babel/core@7.23.5): resolution: {integrity: sha512-zHsy9iXX2nIsCBFPud3jKn1IRPWg3Ing1qOZgeKV39m1ZgIdpJqvlWVeiHBZC6ITRG0MfskhYe9cLgntfSFPIg==} @@ -3541,6 +4223,7 @@ packages: '@babel/core': 7.23.5 '@babel/helper-module-transforms': 7.23.3(@babel/core@7.23.5) '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-named-capturing-groups-regex@7.22.5(@babel/core@7.23.5): resolution: {integrity: sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==} @@ -3551,6 +4234,7 @@ packages: '@babel/core': 7.23.5 '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.23.5) '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-new-target@7.23.3(@babel/core@7.23.5): resolution: {integrity: sha512-YJ3xKqtJMAT5/TIZnpAR3I+K+WaDowYbN3xyxI8zxx/Gsypwf9B9h0VB+1Nh6ACAAPRS5NSRje0uVv5i79HYGQ==} @@ -3560,6 +4244,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-nullish-coalescing-operator@7.23.4(@babel/core@7.23.5): resolution: {integrity: sha512-jHE9EVVqHKAQx+VePv5LLGHjmHSJR76vawFPTdlxR/LVJPfOEGxREQwQfjuZEOPTwG92X3LINSh3M40Rv4zpVA==} @@ -3570,6 +4255,7 @@ packages: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.23.5) + dev: true /@babel/plugin-transform-numeric-separator@7.23.4(@babel/core@7.23.5): resolution: {integrity: sha512-mps6auzgwjRrwKEZA05cOwuDc9FAzoyFS4ZsG/8F43bTLf/TgkJg7QXOrPO1JO599iA3qgK9MXdMGOEC8O1h6Q==} @@ -3580,6 +4266,7 @@ packages: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.23.5) + dev: true /@babel/plugin-transform-object-rest-spread@7.23.4(@babel/core@7.23.5): resolution: {integrity: sha512-9x9K1YyeQVw0iOXJlIzwm8ltobIIv7j2iLyP2jIhEbqPRQ7ScNgwQufU2I0Gq11VjyG4gI4yMXt2VFags+1N3g==} @@ -3593,6 +4280,7 @@ packages: '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.23.5) '@babel/plugin-transform-parameters': 7.23.3(@babel/core@7.23.5) + dev: true /@babel/plugin-transform-object-super@7.23.3(@babel/core@7.23.5): resolution: {integrity: sha512-BwQ8q0x2JG+3lxCVFohg+KbQM7plfpBwThdW9A6TMtWwLsbDA01Ek2Zb/AgDN39BiZsExm4qrXxjk+P1/fzGrA==} @@ -3603,6 +4291,7 @@ packages: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 '@babel/helper-replace-supers': 7.22.20(@babel/core@7.23.5) + dev: true /@babel/plugin-transform-optional-catch-binding@7.23.4(@babel/core@7.23.5): resolution: {integrity: sha512-XIq8t0rJPHf6Wvmbn9nFxU6ao4c7WhghTR5WyV8SrJfUFzyxhCm4nhC+iAp3HFhbAKLfYpgzhJ6t4XCtVwqO5A==} @@ -3613,6 +4302,7 @@ packages: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.23.5) + dev: true /@babel/plugin-transform-optional-chaining@7.23.4(@babel/core@7.23.5): resolution: {integrity: sha512-ZU8y5zWOfjM5vZ+asjgAPwDaBjJzgufjES89Rs4Lpq63O300R/kOz30WCLo6BxxX6QVEilwSlpClnG5cZaikTA==} @@ -3624,6 +4314,7 @@ packages: '@babel/helper-plugin-utils': 7.22.5 '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.23.5) + dev: true /@babel/plugin-transform-parameters@7.23.3(@babel/core@7.23.5): resolution: {integrity: sha512-09lMt6UsUb3/34BbECKVbVwrT9bO6lILWln237z7sLaWnMsTi7Yc9fhX5DLpkJzAGfaReXI22wP41SZmnAA3Vw==} @@ -3633,6 +4324,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-private-methods@7.23.3(@babel/core@7.23.5): resolution: {integrity: sha512-UzqRcRtWsDMTLrRWFvUBDwmw06tCQH9Rl1uAjfh6ijMSmGYQ+fpdB+cnqRC8EMh5tuuxSv0/TejGL+7vyj+50g==} @@ -3643,6 +4335,7 @@ packages: '@babel/core': 7.23.5 '@babel/helper-create-class-features-plugin': 7.23.5(@babel/core@7.23.5) '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-private-property-in-object@7.23.4(@babel/core@7.23.5): resolution: {integrity: sha512-9G3K1YqTq3F4Vt88Djx1UZ79PDyj+yKRnUy7cZGSMe+a7jkwD259uKKuUzQlPkGam7R+8RJwh5z4xO27fA1o2A==} @@ -3655,6 +4348,7 @@ packages: '@babel/helper-create-class-features-plugin': 7.23.5(@babel/core@7.23.5) '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.23.5) + dev: true /@babel/plugin-transform-property-literals@7.23.3(@babel/core@7.23.5): resolution: {integrity: sha512-jR3Jn3y7cZp4oEWPFAlRsSWjxKe4PZILGBSd4nis1TsC5qeSpb+nrtihJuDhNI7QHiVbUaiXa0X2RZY3/TI6Nw==} @@ -3664,6 +4358,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-regenerator@7.23.3(@babel/core@7.23.5): resolution: {integrity: sha512-KP+75h0KghBMcVpuKisx3XTu9Ncut8Q8TuvGO4IhY+9D5DFEckQefOuIsB/gQ2tG71lCke4NMrtIPS8pOj18BQ==} @@ -3674,6 +4369,7 @@ packages: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 regenerator-transform: 0.15.2 + dev: true /@babel/plugin-transform-reserved-words@7.23.3(@babel/core@7.23.5): resolution: {integrity: sha512-QnNTazY54YqgGxwIexMZva9gqbPa15t/x9VS+0fsEFWplwVpXYZivtgl43Z1vMpc1bdPP2PP8siFeVcnFvA3Cg==} @@ -3683,6 +4379,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-shorthand-properties@7.23.3(@babel/core@7.23.5): resolution: {integrity: sha512-ED2fgqZLmexWiN+YNFX26fx4gh5qHDhn1O2gvEhreLW2iI63Sqm4llRLCXALKrCnbN4Jy0VcMQZl/SAzqug/jg==} @@ -3692,6 +4389,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-spread@7.23.3(@babel/core@7.23.5): resolution: {integrity: sha512-VvfVYlrlBVu+77xVTOAoxQ6mZbnIq5FM0aGBSFEcIh03qHf+zNqA4DC/3XMUozTg7bZV3e3mZQ0i13VB6v5yUg==} @@ -3702,6 +4400,7 @@ packages: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 + dev: true /@babel/plugin-transform-sticky-regex@7.23.3(@babel/core@7.23.5): resolution: {integrity: sha512-HZOyN9g+rtvnOU3Yh7kSxXrKbzgrm5X4GncPY1QOquu7epga5MxKHVpYu2hvQnry/H+JjckSYRb93iNfsioAGg==} @@ -3711,6 +4410,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-template-literals@7.23.3(@babel/core@7.23.5): resolution: {integrity: sha512-Flok06AYNp7GV2oJPZZcP9vZdszev6vPBkHLwxwSpaIqx75wn6mUd3UFWsSsA0l8nXAKkyCmL/sR02m8RYGeHg==} @@ -3720,6 +4420,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-typeof-symbol@7.23.3(@babel/core@7.23.5): resolution: {integrity: sha512-4t15ViVnaFdrPC74be1gXBSMzXk3B4Us9lP7uLRQHTFpV5Dvt33pn+2MyyNxmN3VTTm3oTrZVMUmuw3oBnQ2oQ==} @@ -3729,6 +4430,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-typescript@7.23.5(@babel/core@7.23.5): resolution: {integrity: sha512-2fMkXEJkrmwgu2Bsv1Saxgj30IXZdJ+84lQcKKI7sm719oXs0BBw2ZENKdJdR1PjWndgLCEBNXJOri0fk7RYQA==} @@ -3751,6 +4453,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-unicode-property-regex@7.23.3(@babel/core@7.23.5): resolution: {integrity: sha512-KcLIm+pDZkWZQAFJ9pdfmh89EwVfmNovFBcXko8szpBeF8z68kWIPeKlmSOkT9BXJxs2C0uk+5LxoxIv62MROA==} @@ -3761,6 +4464,7 @@ packages: '@babel/core': 7.23.5 '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.23.5) '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-unicode-regex@7.23.3(@babel/core@7.23.5): resolution: {integrity: sha512-wMHpNA4x2cIA32b/ci3AfwNgheiva2W0WUKWTK7vBHBhDKfPsc5cFGNWm69WBqpwd86u1qwZ9PWevKqm1A3yAw==} @@ -3771,6 +4475,7 @@ packages: '@babel/core': 7.23.5 '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.23.5) '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-unicode-sets-regex@7.23.3(@babel/core@7.23.5): resolution: {integrity: sha512-W7lliA/v9bNR83Qc3q1ip9CQMZ09CcHDbHfbLRDNuAhn1Mvkr1ZNF7hPmztMQvtTGVLJ9m8IZqWsTkXOml8dbw==} @@ -3781,6 +4486,7 @@ packages: '@babel/core': 7.23.5 '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.23.5) '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/preset-env@7.23.5(@babel/core@7.23.5): resolution: {integrity: sha512-0d/uxVD6tFGWXGDSfyMD1p2otoaKmu6+GD+NfAx0tMaH+dxORnp7T9TaVQ6mKyya7iBtCIVxHjWT7MuzzM9z+A==} @@ -3871,6 +4577,7 @@ packages: semver: 6.3.1 transitivePeerDependencies: - supports-color + dev: true /@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.23.5): resolution: {integrity: sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==} @@ -3881,6 +4588,7 @@ packages: '@babel/helper-plugin-utils': 7.22.5 '@babel/types': 7.23.5 esutils: 2.0.3 + dev: true /@babel/preset-typescript@7.23.3(@babel/core@7.23.5): resolution: {integrity: sha512-17oIGVlqz6CchO9RFYn5U6ZpWRZIngayYCtrPRSgANSwC2V1Jb+iP74nVxzzXJte8b8BYxrL1yY96xfhTBrNNQ==} @@ -3898,6 +4606,7 @@ packages: /@babel/regjsgen@0.8.0: resolution: {integrity: sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==} + dev: true /@babel/runtime@7.23.5: resolution: {integrity: sha512-NdUTHcPe4C99WxPub+K9l9tK5/lV4UXIoaHSYgzco9BCyjKAAwzdBI+wWtYqHt7LJdbo74ZjRPJgzVweq1sz0w==} @@ -3905,11 +4614,6 @@ packages: dependencies: regenerator-runtime: 0.14.0 - /@babel/standalone@7.23.5: - resolution: {integrity: sha512-4bqgawmyDPu+9gQhZOKh1ftCUa6BAT0KztElMcWAJgOgQJRNhmGVA0M0McedEqvGi7SbfiBBvlH13Jc47P919A==} - engines: {node: '>=6.9.0'} - dev: false - /@babel/template@7.22.15: resolution: {integrity: sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==} engines: {node: '>=6.9.0'} @@ -3917,6 +4621,7 @@ packages: '@babel/code-frame': 7.23.5 '@babel/parser': 7.23.5 '@babel/types': 7.23.5 + dev: true /@babel/traverse@7.23.5: resolution: {integrity: sha512-czx7Xy5a6sapWWRx61m1Ke1Ra4vczu1mCTtJam5zRTBOonfdJ+S/B6HYmGYu3fJtr8GGET3si6IhgWVBhJ/m8w==} @@ -3934,6 +4639,7 @@ packages: globals: 11.12.0 transitivePeerDependencies: - supports-color + dev: true /@babel/types@7.23.5: resolution: {integrity: sha512-ON5kSOJwVO6xXVRTvOI0eOnWe7VdUcIpsovGo9U/Br4Ie4UVFQTboO2cYnDhAGU6Fp+UxSiT+pMft0SMHfuq6w==} @@ -3942,6 +4648,7 @@ packages: '@babel/helper-string-parser': 7.23.4 '@babel/helper-validator-identifier': 7.22.20 to-fast-properties: 2.0.0 + dev: true /@bcoe/v8-coverage@0.2.3: resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} @@ -3961,266 +4668,9 @@ packages: /@cspotcode/source-map-support@0.8.1: resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} - engines: {node: '>=12'} - dependencies: - '@jridgewell/trace-mapping': 0.3.9 - dev: false - - /@cubejs-backend/api-gateway@0.32.31: - resolution: {integrity: sha512-rNvgBbyI6zJgXyLecTru5lpJb0XAEFzxs+1PMUoHRdw22EDttPJwzoAsN7q3tZl6ukXtBhqcmMkjQRdaUSiuRQ==} - engines: {node: ^14.0.0 || ^16.0.0 || >=17.0.0} - dependencies: - '@cubejs-backend/native': 0.32.31(moment@2.29.4) - '@cubejs-backend/shared': 0.32.30(moment@2.29.4) - '@ungap/structured-clone': 0.3.4 - body-parser: 1.20.2 - chrono-node: 2.7.3 - express-graphql: 0.12.0(graphql@15.8.0) - graphql: 15.8.0 - graphql-scalars: 1.22.4(graphql@15.8.0) - inflection: 1.13.4 - joi: 17.11.0 - jsonwebtoken: 8.5.1 - jwk-to-pem: 2.0.5 - moment: 2.29.4 - moment-timezone: 0.5.43 - nexus: 1.3.0(graphql@15.8.0) - node-fetch: 2.7.0 - querystring: 0.2.1 - ramda: 0.27.2 - uuid: 8.3.2 - transitivePeerDependencies: - - encoding - - supports-color - dev: false - - /@cubejs-backend/base-driver@0.32.30(moment@2.29.4): - resolution: {integrity: sha512-pVNGoTCwKvgWu32ecknUzzwf0dSKCpjsuceIgKn2BSh7x4Oh89tbD5w6UaQ0qZbihmvOOglcsW3to9c0Hg0rqw==} - engines: {node: ^14.0.0 || ^16.0.0 || >=17.0.0} - dependencies: - '@cubejs-backend/shared': 0.32.30(moment@2.29.4) - ramda: 0.27.2 - transitivePeerDependencies: - - encoding - - moment - - supports-color - dev: false - - /@cubejs-backend/cloud@0.32.30(moment@2.29.4): - resolution: {integrity: sha512-87CuekqJ52IVsqpg3UGCq8+8AAEIAar5NJuCJXhkQYy/q2OW08mHOyF7td1s14CMsjkdfwwKFeGT41DvLi8JVQ==} - engines: {node: ^14.0.0 || ^16.0.0 || >=17.0.0} - dependencies: - '@cubejs-backend/dotenv': 9.0.2 - '@cubejs-backend/shared': 0.32.30(moment@2.29.4) - chokidar: 3.5.3 - env-var: 6.3.0 - fs-extra: 9.1.0 - jsonwebtoken: 8.5.1 - request: 2.88.2 - request-promise: 4.2.6(request@2.88.2) - transitivePeerDependencies: - - encoding - - moment - - supports-color - dev: false - - /@cubejs-backend/cubesql@0.32.31: - resolution: {integrity: sha512-L4tLmTny3K9CWTDAgrVAtXc0ZQi+iPY9g4LTRZRYhM3Ef02dOwVgpFP5YLnu8/V2hC2CehdrfZT9GYWRsfOkXQ==} - engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - dev: false - - /@cubejs-backend/cubestore-driver@0.32.30(bufferutil@4.0.8)(moment@2.29.4)(utf-8-validate@5.0.10): - resolution: {integrity: sha512-bU+23IlDERpgQkUyuivO6kVVww5nadF04TsLnifQz9qZJMesrJElM5Csmo+GA8JX4ZOl+ARstxmaNkLfRNt4+A==} - engines: {node: ^14.0.0 || ^16.0.0 || >=17.0.0} - dependencies: - '@cubejs-backend/base-driver': 0.32.30(moment@2.29.4) - '@cubejs-backend/cubestore': 0.32.30(moment@2.29.4) - '@cubejs-backend/shared': 0.32.30(moment@2.29.4) - csv-write-stream: 2.0.0 - flatbuffers: 23.3.3 - fs-extra: 9.1.0 - generic-pool: 3.9.0 - moment-timezone: 0.5.43 - node-fetch: 2.7.0 - sqlstring: 2.3.3 - tempy: 1.0.1 - uuid: 8.3.2 - ws: 7.5.9(bufferutil@4.0.8)(utf-8-validate@5.0.10) - transitivePeerDependencies: - - bufferutil - - encoding - - moment - - supports-color - - utf-8-validate - dev: false - - /@cubejs-backend/cubestore@0.32.30(moment@2.29.4): - resolution: {integrity: sha512-Y2+GTKXsHJHhfoWcUuaNuuneC2NGeWu+a5Uc0Mxyg8uYV7eUsxrgwoQDEPTR9zvxpeTEoOZXS9wDG6EzloECWg==} - engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - hasBin: true - requiresBuild: true - dependencies: - '@cubejs-backend/shared': 0.32.30(moment@2.29.4) - '@octokit/core': 3.6.0 - source-map-support: 0.5.21 - transitivePeerDependencies: - - encoding - - moment - - supports-color - dev: false - - /@cubejs-backend/dotenv@9.0.2: - resolution: {integrity: sha512-yC1juhXEjM7K97KfXubDm7WGipd4Lpxe+AT8XeTRE9meRULrKlw0wtE2E8AQkGOfTBn+P1SCkePQ/BzIbOh1VA==} - engines: {node: '>=8'} - dev: false - - /@cubejs-backend/native@0.32.31(moment@2.29.4): - resolution: {integrity: sha512-vCp2a7rcKlMpuu5w0t8ea+f+Wx4EhDUR3whM2penEf+W9aoj85TWudLop3VifN30UCf+iDGQWY2TMYSQlQDSVQ==} - engines: {node: ^14.0.0 || ^16.0.0 || >=17.0.0} - requiresBuild: true - dependencies: - '@cubejs-backend/cubesql': 0.32.31 - '@cubejs-backend/shared': 0.32.30(moment@2.29.4) - '@mapbox/node-pre-gyp': 1.0.11 - transitivePeerDependencies: - - encoding - - moment - - supports-color - dev: false - - /@cubejs-backend/query-orchestrator@0.32.30(bufferutil@4.0.8)(moment@2.29.4)(utf-8-validate@5.0.10): - resolution: {integrity: sha512-+OVqaBC3X6I5CEAy45ej9FpVABrY+us5Z9bzbhA7zCCzSFqaY8cCGqpNK6PVqapimlVGM4ByjqQ4ViwCoFT6nA==} - engines: {node: ^14.0.0 || ^16.0.0 || >=17.0.0} - dependencies: - '@cubejs-backend/base-driver': 0.32.30(moment@2.29.4) - '@cubejs-backend/cubestore-driver': 0.32.30(bufferutil@4.0.8)(moment@2.29.4)(utf-8-validate@5.0.10) - '@cubejs-backend/shared': 0.32.30(moment@2.29.4) - csv-write-stream: 2.0.0 - es5-ext: 0.10.53 - generic-pool: 3.9.0 - ioredis: 4.28.5 - lru-cache: 6.0.0 - moment-range: 4.0.2(moment@2.29.4) - moment-timezone: 0.5.43 - ramda: 0.27.2 - redis: 3.1.2 - transitivePeerDependencies: - - bufferutil - - encoding - - moment - - supports-color - - utf-8-validate - dev: false - - /@cubejs-backend/schema-compiler@0.32.31(moment@2.29.4): - resolution: {integrity: sha512-ttZbuirP9ZnATYAONsa6+ChtwYA6uvR6Z49OPlLhKbiys/2ske7OZZOMDByzgZ6AnOd4T8arYta25p+oOyqbog==} - engines: {node: ^14.0.0 || ^16.0.0 || >=17.0.0} - dependencies: - '@babel/code-frame': 7.23.5 - '@babel/core': 7.23.5 - '@babel/generator': 7.23.5 - '@babel/parser': 7.23.5 - '@babel/preset-env': 7.23.5(@babel/core@7.23.5) - '@babel/standalone': 7.23.5 - '@babel/traverse': 7.23.5 - '@babel/types': 7.23.5 - '@cubejs-backend/shared': 0.32.30(moment@2.29.4) - antlr4ts: 0.5.0-alpha.4 - camelcase: 6.3.0 - cron-parser: 3.5.0 - humps: 2.0.1 - inflection: 1.13.4 - joi: 17.11.0 - js-yaml: 4.1.0 - lru-cache: 5.1.1 - moment-range: 4.0.2(moment@2.29.4) - moment-timezone: 0.5.43 - node-dijkstra: 2.5.0 - ramda: 0.27.2 - syntax-error: 1.4.0 - transitivePeerDependencies: - - encoding - - moment - - supports-color - dev: false - - /@cubejs-backend/server-core@0.32.31(bufferutil@4.0.8)(utf-8-validate@5.0.10): - resolution: {integrity: sha512-vFMk4ktPMOOLGo98T5TKgLZyWfy4xQSjQEjQnRE3kNGDaD161ypmP/Q72SlsACyJdtvlsyeTXTEuC7mlsGaY4g==} - engines: {node: ^14.0.0 || ^16.0.0 || >=17.0.0} - dependencies: - '@cubejs-backend/api-gateway': 0.32.31 - '@cubejs-backend/cloud': 0.32.30(moment@2.29.4) - '@cubejs-backend/dotenv': 9.0.2 - '@cubejs-backend/query-orchestrator': 0.32.30(bufferutil@4.0.8)(moment@2.29.4)(utf-8-validate@5.0.10) - '@cubejs-backend/schema-compiler': 0.32.31(moment@2.29.4) - '@cubejs-backend/shared': 0.32.30(moment@2.29.4) - '@cubejs-backend/templates': 0.32.30(moment@2.29.4) - codesandbox-import-utils: 2.2.3 - cross-spawn: 7.0.3 - fs-extra: 8.1.0 - is-docker: 2.2.1 - joi: 17.11.0 - jsonwebtoken: 8.5.1 - lodash.clonedeep: 4.5.0 - lru-cache: 5.1.1 - moment: 2.29.4 - node-fetch: 2.7.0 - p-limit: 3.1.0 - promise-timeout: 1.3.0 - ramda: 0.27.2 - semver: 6.3.1 - serve-static: 1.15.0 - sqlstring: 2.3.3 - uuid: 8.3.2 - ws: 7.5.9(bufferutil@4.0.8)(utf-8-validate@5.0.10) - transitivePeerDependencies: - - bufferutil - - encoding - - supports-color - - utf-8-validate - dev: false - - /@cubejs-backend/shared@0.32.30(moment@2.29.4): - resolution: {integrity: sha512-491ePbWjdrkmiuirInciM2++WIFwNirSBGshX/xi8qKvPMNqOp5rkeAUPoKk8yCJF7rqDn38hCzln9HbsRWBRQ==} - engines: {node: ^14.0.0 || ^16.0.0 || >=17.0.0} - dependencies: - '@oclif/color': 0.1.2 - bytes: 3.1.2 - cli-progress: 3.12.0 - cross-spawn: 7.0.3 - decompress: 4.2.1 - env-var: 6.3.0 - fs-extra: 9.1.0 - http-proxy-agent: 4.0.1 - moment-range: 4.0.2(moment@2.29.4) - moment-timezone: 0.5.43 - node-fetch: 2.7.0 - shelljs: 0.8.5 - throttle-debounce: 3.0.1 - uuid: 8.3.2 - transitivePeerDependencies: - - encoding - - moment - - supports-color - dev: false - - /@cubejs-backend/templates@0.32.30(moment@2.29.4): - resolution: {integrity: sha512-Y96kcc249g5DyfZ4QMtY8SkOtWY2fH8kJMPr1Pjn2FYEy7HJtnb98gy0BgXKvmL7tD4iqlj88lDGMdvOEIRoDw==} - engines: {node: ^14.0.0 || ^16.0.0 || >=17.0.0} - dependencies: - '@cubejs-backend/shared': 0.32.30(moment@2.29.4) - cross-spawn: 7.0.3 - decompress: 4.2.1 - decompress-targz: 4.1.1 - fs-extra: 9.1.0 - node-fetch: 2.7.0 - ramda: 0.27.2 - source-map-support: 0.5.21 - transitivePeerDependencies: - - encoding - - moment - - supports-color - dev: false + engines: {node: '>=12'} + dependencies: + '@jridgewell/trace-mapping': 0.3.9 /@cubejs-client/core@0.30.74: resolution: {integrity: sha512-InZa/nKw1ldzvRui0nuZvLGrtYZOmGmIa1gCrCU4i9wAR7pQjlTL2nK+kZ6XLZ5MsuZGWgi3LZNNRkz1wNeiwA==} @@ -4480,7 +4930,7 @@ packages: engines: {node: ^8.13.0 || >=10.10.0} dependencies: '@grpc/proto-loader': 0.7.10 - '@types/node': 20.10.1 + '@types/node': 20.10.7 dev: false /@grpc/grpc-js@1.9.12: @@ -4488,7 +4938,7 @@ packages: engines: {node: ^8.13.0 || >=10.10.0} dependencies: '@grpc/proto-loader': 0.7.10 - '@types/node': 20.10.1 + '@types/node': 20.10.7 dev: false /@grpc/proto-loader@0.7.10: @@ -4502,16 +4952,6 @@ packages: yargs: 17.7.2 dev: false - /@hapi/hoek@9.3.0: - resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==} - dev: false - - /@hapi/topo@5.1.0: - resolution: {integrity: sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==} - dependencies: - '@hapi/hoek': 9.3.0 - dev: false - /@humanwhocodes/config-array@0.11.13: resolution: {integrity: sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==} engines: {node: '>=10.10.0'} @@ -4567,7 +5007,7 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@jest/types': 29.6.3 - '@types/node': 20.10.1 + '@types/node': 20.10.7 chalk: 4.1.2 jest-message-util: 29.7.0 jest-util: 29.7.0 @@ -4588,14 +5028,14 @@ packages: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.10.1 + '@types/node': 20.10.7 ansi-escapes: 4.3.2 chalk: 4.1.2 ci-info: 3.9.0 exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@20.10.1)(ts-node@10.6.0) + jest-config: 29.7.0(@types/node@20.10.7)(ts-node@10.6.0) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -4623,7 +5063,7 @@ packages: dependencies: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.10.1 + '@types/node': 20.10.7 jest-mock: 29.7.0 dev: true @@ -4650,7 +5090,7 @@ packages: dependencies: '@jest/types': 29.6.3 '@sinonjs/fake-timers': 10.3.0 - '@types/node': 20.10.1 + '@types/node': 20.10.7 jest-message-util: 29.7.0 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -4683,7 +5123,7 @@ packages: '@jest/transform': 29.7.0 '@jest/types': 29.6.3 '@jridgewell/trace-mapping': 0.3.20 - '@types/node': 20.10.1 + '@types/node': 20.10.7 chalk: 4.1.2 collect-v8-coverage: 1.0.2 exit: 0.1.2 @@ -4771,7 +5211,7 @@ packages: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 20.10.1 + '@types/node': 20.10.7 '@types/yargs': 17.0.32 chalk: 4.1.2 dev: true @@ -4813,30 +5253,11 @@ packages: dependencies: '@jridgewell/resolve-uri': 3.1.1 '@jridgewell/sourcemap-codec': 1.4.15 - dev: false /@jsdevtools/ono@7.1.3: resolution: {integrity: sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==} dev: true - /@mapbox/node-pre-gyp@1.0.11: - resolution: {integrity: sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==} - hasBin: true - dependencies: - detect-libc: 2.0.2 - https-proxy-agent: 5.0.1 - make-dir: 3.1.0 - node-fetch: 2.7.0 - nopt: 5.0.0 - npmlog: 5.0.1 - rimraf: 3.0.2 - semver: 7.5.4 - tar: 6.2.0 - transitivePeerDependencies: - - encoding - - supports-color - dev: false - /@nodelib/fs.scandir@2.1.5: resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -4872,18 +5293,6 @@ packages: rimraf: 3.0.2 dev: false - /@oclif/color@0.1.2: - resolution: {integrity: sha512-M9o+DOrb8l603qvgz1FogJBUGLqcMFL1aFg2ZEL0FbXJofiNTLOWIeB4faeZTLwE6dt0xH9GpCVpzksMMzGbmA==} - engines: {node: '>=8.0.0'} - deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. - dependencies: - ansi-styles: 3.2.1 - chalk: 3.0.0 - strip-ansi: 5.2.0 - supports-color: 5.5.0 - tslib: 1.14.1 - dev: false - /@octokit/auth-app@3.6.1: resolution: {integrity: sha512-6oa6CFphIYI7NxxHrdVOzhG7hkcKyGyYocg7lNDSJVauVOLtylg8hNJzoUyPAYKKK0yUeoZamE/lMs2tG+S+JA==} dependencies: @@ -4997,26 +5406,6 @@ packages: - encoding dev: false - /@octokit/auth-token@2.5.0: - resolution: {integrity: sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==} - dependencies: - '@octokit/types': 6.41.0 - dev: false - - /@octokit/core@3.6.0: - resolution: {integrity: sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==} - dependencies: - '@octokit/auth-token': 2.5.0 - '@octokit/graphql': 4.8.0 - '@octokit/request': 5.6.3 - '@octokit/request-error': 2.1.0 - '@octokit/types': 6.41.0 - before-after-hook: 2.2.3 - universal-user-agent: 6.0.1 - transitivePeerDependencies: - - encoding - dev: false - /@octokit/endpoint@6.0.12: resolution: {integrity: sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==} dependencies: @@ -5950,12 +6339,12 @@ packages: selderee: 0.6.0 dev: false - /@sendgrid/client@7.7.0: - resolution: {integrity: sha512-SxH+y8jeAQSnDavrTD0uGDXYIIkFylCo+eDofVmZLQ0f862nnqbC3Vd1ej6b7Le7lboyzQF6F7Fodv02rYspuA==} - engines: {node: 6.* || 8.* || >=10.*} + /@sendgrid/client@8.1.0: + resolution: {integrity: sha512-Kp2kKLr307v/HnR3uGuySt0AbCkeG7naDVOzfPOtWvKHVZIEHmKidQjJjzytVZNYWtoRdYgNfBw6GyUznGqa6w==} + engines: {node: '>=12.*'} dependencies: - '@sendgrid/helpers': 7.7.0 - axios: 0.26.1 + '@sendgrid/helpers': 8.0.0 + axios: 1.6.2 transitivePeerDependencies: - debug dev: false @@ -5967,47 +6356,23 @@ packages: starkbank-ecdsa: 1.1.5 dev: false - /@sendgrid/helpers@7.7.0: - resolution: {integrity: sha512-3AsAxfN3GDBcXoZ/y1mzAAbKzTtUZ5+ZrHOmWQ279AuaFXUNCh9bPnRpN504bgveTqoW+11IzPg3I0WVgDINpw==} - engines: {node: '>= 6.0.0'} + /@sendgrid/helpers@8.0.0: + resolution: {integrity: sha512-Ze7WuW2Xzy5GT5WRx+yEv89fsg/pgy3T1E3FS0QEx0/VvRmigMZ5qyVGhJz4SxomegDkzXv/i0aFPpHKN8qdAA==} + engines: {node: '>= 12.0.0'} dependencies: deepmerge: 4.3.1 dev: false - /@sendgrid/mail@7.2.6: - resolution: {integrity: sha512-eP9MuqEZIgt4bHaoufWqKGUY4Bo7FUgST3WGNYIDXIe1rP2dV6/JR7Ac2Dl9iW22gy15nc58fLGIGa41XbwtuA==} - engines: {node: 6.* || 8.* || >=10.*} - dependencies: - '@sendgrid/client': 7.7.0 - '@sendgrid/helpers': 7.7.0 - transitivePeerDependencies: - - debug - dev: false - - /@sendgrid/mail@7.7.0: - resolution: {integrity: sha512-5+nApPE9wINBvHSUxwOxkkQqM/IAAaBYoP9hw7WwgDNQPxraruVqHizeTitVtKGiqWCKm2mnjh4XGN3fvFLqaw==} - engines: {node: 6.* || 8.* || >=10.*} + /@sendgrid/mail@8.1.0: + resolution: {integrity: sha512-WkE0qwOrJMX9oQ+Xvtl3CdmucD6/iKw6go0VPoPieVlfXc43rbIf91wvtO6m7sKPnzxw3G+8rekBgXibmP4S8Q==} + engines: {node: '>=12.*'} dependencies: - '@sendgrid/client': 7.7.0 - '@sendgrid/helpers': 7.7.0 + '@sendgrid/client': 8.1.0 + '@sendgrid/helpers': 8.0.0 transitivePeerDependencies: - debug dev: false - /@sideway/address@4.1.4: - resolution: {integrity: sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==} - dependencies: - '@hapi/hoek': 9.3.0 - dev: false - - /@sideway/formula@3.0.1: - resolution: {integrity: sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==} - dev: false - - /@sideway/pinpoint@2.0.0: - resolution: {integrity: sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==} - dev: false - /@sinclair/typebox@0.27.8: resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} dev: true @@ -6033,7 +6398,7 @@ packages: resolution: {integrity: sha512-DTuBFbqu4gGfajREEMrkq5jBhcnskinhr4+AnfJEk48zhVeEv3XnUKGIX98B74kxhYsIMfApGGySTn7V3b5yBA==} engines: {node: '>= 12.13.0', npm: '>= 6.12.0'} dependencies: - '@types/node': 20.10.1 + '@types/node': 20.10.7 dev: false /@slack/types@2.10.0: @@ -6048,7 +6413,7 @@ packages: '@slack/logger': 3.0.0 '@slack/types': 2.10.0 '@types/is-stream': 1.1.0 - '@types/node': 20.10.1 + '@types/node': 20.10.7 axios: 1.6.2 eventemitter3: 3.1.2 form-data: 2.5.1 @@ -6736,11 +7101,6 @@ packages: '@temporalio/proto': 1.8.6 dev: false - /@tootallnate/once@1.1.2: - resolution: {integrity: sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==} - engines: {node: '>= 6'} - dev: false - /@tootallnate/once@2.0.0: resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==} engines: {node: '>= 10'} @@ -6795,7 +7155,7 @@ packages: resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} dependencies: '@types/connect': 3.4.38 - '@types/node': 20.10.1 + '@types/node': 20.10.7 dev: false /@types/btoa-lite@1.0.2: @@ -6805,18 +7165,18 @@ packages: /@types/bunyan-format@0.2.9: resolution: {integrity: sha512-WuHXkdlVOzNejhWMO7mSu+i81rpp3b1pGB8HDCv+HtOGkz0gpoTSKfaQfDgYDUKI0BfZM4XRNGsVSI11akwrEQ==} dependencies: - '@types/node': 20.10.1 + '@types/node': 20.10.7 dev: true /@types/bunyan@1.8.11: resolution: {integrity: sha512-758fRH7umIMk5qt5ELmRMff4mLDlN+xyYzC+dkPTdKwbSkJFvz6xwyScrytPU0QIBbRRwbiE8/BIg8bpajerNQ==} dependencies: - '@types/node': 20.10.1 + '@types/node': 20.10.7 /@types/bunyan@1.8.9: resolution: {integrity: sha512-ZqS9JGpBxVOvsawzmVt30sP++gSQMTejCkIAQ3VdadOcRE8izTyW66hufvwLeH+YEGP6Js2AW7Gz+RMyvrEbmw==} dependencies: - '@types/node': 20.10.1 + '@types/node': 20.10.7 dev: false /@types/config@3.3.3: @@ -6825,7 +7185,7 @@ packages: /@types/connect@3.4.38: resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} dependencies: - '@types/node': 20.10.1 + '@types/node': 20.10.7 dev: false /@types/cookie@0.4.1: @@ -6838,7 +7198,7 @@ packages: /@types/cors@2.8.17: resolution: {integrity: sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==} dependencies: - '@types/node': 20.10.1 + '@types/node': 20.10.7 dev: false /@types/cron@2.4.0: @@ -6875,7 +7235,7 @@ packages: /@types/express-serve-static-core@4.17.41: resolution: {integrity: sha512-OaJ7XLaelTgrvlZD8/aa0vvvxZdUmlCn6MtWeB7TkiKW70BQLc9XEPpDLPdbo52ZhXUCrznlWdCHWxJWtdyajA==} dependencies: - '@types/node': 20.10.1 + '@types/node': 20.10.7 '@types/qs': 6.9.10 '@types/range-parser': 1.2.7 '@types/send': 0.17.4 @@ -6902,7 +7262,7 @@ packages: /@types/graceful-fs@4.1.9: resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==} dependencies: - '@types/node': 20.10.1 + '@types/node': 20.10.7 dev: true /@types/he@1.2.3: @@ -6924,7 +7284,7 @@ packages: /@types/is-stream@1.1.0: resolution: {integrity: sha512-jkZatu4QVbR60mpIzjINmtS1ZF4a/FqdTUTBeQDVOQ2PYyidtwFKr0B5G6ERukKwliq+7mIXvxyppwzG5EgRYg==} dependencies: - '@types/node': 20.10.1 + '@types/node': 20.10.7 dev: false /@types/istanbul-lib-coverage@2.0.6: @@ -6960,13 +7320,13 @@ packages: /@types/jsonwebtoken@9.0.5: resolution: {integrity: sha512-VRLSGzik+Unrup6BsouBeHsf4d1hOEgYWTm/7Nmw1sXoN1+tRly/Gy/po3yeahnP4jfnQWWAhQAqcNfH7ngOkA==} dependencies: - '@types/node': 20.10.1 + '@types/node': 20.10.7 dev: false /@types/keyv@3.1.4: resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} dependencies: - '@types/node': 20.10.1 + '@types/node': 20.10.7 dev: true /@types/lru-cache@5.1.1: @@ -7002,11 +7362,16 @@ packages: dependencies: undici-types: 5.26.5 + /@types/node@20.10.7: + resolution: {integrity: sha512-fRbIKb8C/Y2lXxB5eVMj4IU7xpdox0Lh8bUPEdtLysaylsml1hOOx1+STloRs/B9nf7C6kPRmmg/V7aQW7usNg==} + dependencies: + undici-types: 5.26.5 + /@types/oauth@0.9.4: resolution: {integrity: sha512-qk9orhti499fq5XxKCCEbd0OzdPZuancneyse3KtR+vgMiHRbh+mn8M4G6t64ob/Fg+GZGpa565MF/2dKWY32A==} requiresBuild: true dependencies: - '@types/node': 20.10.1 + '@types/node': 20.10.7 dev: false optional: true @@ -7037,7 +7402,7 @@ packages: /@types/pg@8.6.1: resolution: {integrity: sha512-1Kc4oAGzAl7uqUStZCDvaLFqZrW9qWSjXOmBfdgyBP5La7Us6Mg4GBvRlSoaZMhQF/zSj1C8CtKMBkoiT8eL8w==} dependencies: - '@types/node': 20.10.1 + '@types/node': 20.10.7 pg-protocol: 1.6.0 pg-types: 2.2.0 dev: false @@ -7053,7 +7418,7 @@ packages: /@types/responselike@1.0.3: resolution: {integrity: sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==} dependencies: - '@types/node': 20.10.1 + '@types/node': 20.10.7 dev: true /@types/retry@0.12.0: @@ -7073,7 +7438,7 @@ packages: resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==} dependencies: '@types/mime': 1.3.5 - '@types/node': 20.10.1 + '@types/node': 20.10.7 dev: false /@types/serve-static@1.15.5: @@ -7081,7 +7446,7 @@ packages: dependencies: '@types/http-errors': 2.0.4 '@types/mime': 3.0.4 - '@types/node': 20.10.1 + '@types/node': 20.10.7 dev: false /@types/shimmer@1.0.5: @@ -7096,7 +7461,7 @@ packages: resolution: {integrity: sha512-mEafCgyKiMFin24SDzWN7yAADt4gt6YawFiNMp0QS5ZPboORfyxFt0s3VzJKhTaKg9py/4FUmrHLTNfJKt9Rbw==} dependencies: '@types/cookiejar': 2.1.5 - '@types/node': 20.10.1 + '@types/node': 20.10.7 /@types/uuid@9.0.7: resolution: {integrity: sha512-WUtIVRUZ9i5dYXefDEAI7sh9/O7jGvHg7Df/5O/gtH3Yabe5odI3UWopVR1qbPXQtvOxWu3mM4XxlYeZtMWF4g==} @@ -7109,7 +7474,7 @@ packages: /@types/ws@8.5.9: resolution: {integrity: sha512-jbdrY0a8lxfdTp/+r7Z4CkycbOFN8WX+IOchLJr3juT/xzbJ8URyTVSJ/hvNdadTgM1mnedb47n+Y31GsFnQlg==} dependencies: - '@types/node': 20.10.1 + '@types/node': 20.10.7 dev: false /@types/yargs-parser@21.0.3: @@ -7375,13 +7740,14 @@ packages: eslint-visitor-keys: 3.4.3 dev: true - /@ungap/structured-clone@0.3.4: - resolution: {integrity: sha512-TSVh8CpnwNAsPC5wXcIyh92Bv1gq6E9cNDeeLu7Z4h8V4/qWtXJp7y42qljRkqcpmsve1iozwv1wr+3BNdILCg==} - dev: false - /@ungap/structured-clone@1.2.0: resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} + /@vercel/ncc@0.38.1: + resolution: {integrity: sha512-IBBb+iI2NLu4VQn3Vwldyi2QwaXt5+hTyh58ggAMoCGE6DJmPvwL3KPBWcJl1m9LYPChBLE980Jw+CS4Wokqxw==} + hasBin: true + dev: true + /@vladfrangu/async_event_emitter@2.2.2: resolution: {integrity: sha512-HIzRG7sy88UZjBJamssEczH5q7t5+axva19UbZLO6u0ySbYPrwzWiXBcC0WuHyhKKoeCyneH+FvYzKQq/zTtkQ==} engines: {node: '>=v14.0.0', npm: '>=7.0.0'} @@ -7543,29 +7909,10 @@ packages: dependencies: acorn: 8.11.2 - /acorn-node@1.8.2: - resolution: {integrity: sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==} - dependencies: - acorn: 7.4.1 - acorn-walk: 7.2.0 - xtend: 4.0.2 - dev: false - - /acorn-walk@7.2.0: - resolution: {integrity: sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==} - engines: {node: '>=0.4.0'} - dev: false - /acorn-walk@8.3.0: resolution: {integrity: sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA==} engines: {node: '>=0.4.0'} - /acorn@7.4.1: - resolution: {integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==} - engines: {node: '>=0.4.0'} - hasBin: true - dev: false - /acorn@8.11.2: resolution: {integrity: sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==} engines: {node: '>=0.4.0'} @@ -7707,11 +8054,6 @@ packages: engines: {node: '>=4'} dev: false - /ansi-regex@4.1.1: - resolution: {integrity: sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==} - engines: {node: '>=6'} - dev: false - /ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -7751,10 +8093,6 @@ packages: resolution: {integrity: sha512-6QWEyvMgIXX0eO972y7YPBLSBsq7UWKFAoNNTLGaOJ9bstcEL9sCbcjf96dVfNDdUsRoGOK82vWFJlKApXds7g==} dev: false - /antlr4ts@0.5.0-alpha.4: - resolution: {integrity: sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ==} - dev: false - /any-promise@1.3.0: resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} dev: false @@ -7770,10 +8108,6 @@ packages: resolution: {integrity: sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==} dev: false - /aproba@2.0.0: - resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} - dev: false - /are-we-there-yet@1.1.7: resolution: {integrity: sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==} dependencies: @@ -7781,14 +8115,6 @@ packages: readable-stream: 2.3.8 dev: false - /are-we-there-yet@2.0.0: - resolution: {integrity: sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==} - engines: {node: '>=10'} - dependencies: - delegates: 1.0.0 - readable-stream: 3.6.2 - dev: false - /arg@4.1.3: resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} @@ -7890,31 +8216,11 @@ packages: /asap@2.0.6: resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} - /asn1.js@5.4.1: - resolution: {integrity: sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==} - dependencies: - bn.js: 4.12.0 - inherits: 2.0.4 - minimalistic-assert: 1.0.1 - safer-buffer: 2.1.2 - dev: false - - /asn1@0.2.6: - resolution: {integrity: sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==} - dependencies: - safer-buffer: 2.1.2 - dev: false - /assert-options@0.8.1: resolution: {integrity: sha512-5lNGRB5g5i2bGIzb+J1QQE1iKU/WEMVBReFIc5pPDWjcPj23otPL0eI6PB2v7QPi0qU6Mhym5D3y0ZiSIOf3GA==} engines: {node: '>=10.0.0'} dev: false - /assert-plus@1.0.0: - resolution: {integrity: sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==} - engines: {node: '>=0.8'} - dev: false - /ast-types@0.13.4: resolution: {integrity: sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==} engines: {node: '>=4'} @@ -7949,11 +8255,6 @@ packages: /asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - /at-least-node@1.0.0: - resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==} - engines: {node: '>= 4.0.0'} - dev: false - /available-typed-arrays@1.0.5: resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} engines: {node: '>= 0.4'} @@ -7974,10 +8275,6 @@ packages: xml2js: 0.4.19 dev: false - /aws-sign2@0.7.0: - resolution: {integrity: sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==} - dev: false - /aws4@1.12.0: resolution: {integrity: sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==} dev: false @@ -7996,14 +8293,6 @@ packages: - debug dev: false - /axios@0.26.1: - resolution: {integrity: sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==} - dependencies: - follow-redirects: 1.15.3(debug@4.3.4) - transitivePeerDependencies: - - debug - dev: false - /axios@0.27.2: resolution: {integrity: sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==} dependencies: @@ -8085,6 +8374,7 @@ packages: semver: 6.3.1 transitivePeerDependencies: - supports-color + dev: true /babel-plugin-polyfill-corejs3@0.8.6(@babel/core@7.23.5): resolution: {integrity: sha512-leDIc4l4tUgU7str5BWLS2h8q2N4Nf6lGZP6UrNDxdtfF2g69eJ5L0H7S8A5Ln/arfFAfHor5InAdZuIOwZdgQ==} @@ -8096,6 +8386,7 @@ packages: core-js-compat: 3.33.3 transitivePeerDependencies: - supports-color + dev: true /babel-plugin-polyfill-regenerator@0.5.3(@babel/core@7.23.5): resolution: {integrity: sha512-8sHeDOmXC8csczMrYEOf0UTNa4yE2SxV5JGeT/LP1n0OYVDUUFPxG9vdk2AlDlIit4t+Kf0xCtpgXPBwnn/9pw==} @@ -8106,6 +8397,7 @@ packages: '@babel/helper-define-polyfill-provider': 0.4.3(@babel/core@7.23.5) transitivePeerDependencies: - supports-color + dev: true /babel-preset-current-node-syntax@1.0.1(@babel/core@7.23.5): resolution: {integrity: sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==} @@ -8159,12 +8451,6 @@ packages: engines: {node: '>=10.0.0'} dev: false - /bcrypt-pbkdf@1.0.2: - resolution: {integrity: sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==} - dependencies: - tweetnacl: 0.14.5 - dev: false - /bcrypt@5.0.0: resolution: {integrity: sha512-jB0yCBl4W/kVHM2whjfyqnxTmOHkCX4kHEa5nYKSoGeYe8YrjTYTc87/6bwt1g8cmV0QrbhKriETg9jWtcREhg==} engines: {node: '>= 10.0.0'} @@ -8176,10 +8462,6 @@ packages: - supports-color dev: false - /before-after-hook@2.2.3: - resolution: {integrity: sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==} - dev: false - /big-integer@1.6.52: resolution: {integrity: sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==} engines: {node: '>=0.6'} @@ -8192,24 +8474,12 @@ packages: resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} engines: {node: '>=8'} - /binaryextensions@2.3.0: - resolution: {integrity: sha512-nAihlQsYGyc5Bwq6+EsubvANYGExeJKHDO3RjnvwU042fawQTQfM3Kxn7IHUXQOz4bzfwsGYYHGSvXyW4zOGLg==} - engines: {node: '>=0.8'} - dev: false - /bindings@1.5.0: resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} dependencies: file-uri-to-path: 1.0.0 dev: false - /bl@1.2.3: - resolution: {integrity: sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==} - dependencies: - readable-stream: 2.3.8 - safe-buffer: 5.2.1 - dev: false - /bl@4.1.0: resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} dependencies: @@ -8232,10 +8502,6 @@ packages: resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==} dev: false - /bn.js@4.12.0: - resolution: {integrity: sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==} - dev: false - /bodec@0.1.0: resolution: {integrity: sha512-Ylo+MAo5BDUq1KA3f3R/MFhh+g8cnHmo8bz3YPGhI1znrMaf77ol1sfvYJzsw3nTE+Y2GryfDxBaR+AqpAkEHQ==} dev: false @@ -8359,10 +8625,6 @@ packages: dependencies: fill-range: 7.0.1 - /brorand@1.1.0: - resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==} - dev: false - /browserslist@4.22.1: resolution: {integrity: sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} @@ -8390,29 +8652,10 @@ packages: resolution: {integrity: sha512-gvW7InbIyF8AicrqWoptdW08pUxuhq8BEgowNajy9RhiE86fmGAGl+bLKo6oB8QP0CkqHLowfN0oJdKC/J6LbA==} dev: false - /buffer-alloc-unsafe@1.1.0: - resolution: {integrity: sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==} - dev: false - - /buffer-alloc@1.2.0: - resolution: {integrity: sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==} - dependencies: - buffer-alloc-unsafe: 1.1.0 - buffer-fill: 1.0.0 - dev: false - - /buffer-crc32@0.2.13: - resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} - dev: false - /buffer-equal-constant-time@1.0.1: resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} dev: false - /buffer-fill@1.0.0: - resolution: {integrity: sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==} - dev: false - /buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} @@ -8434,6 +8677,7 @@ packages: dependencies: base64-js: 1.5.1 ieee754: 1.2.1 + dev: true /bufferutil@4.0.8: resolution: {integrity: sha512-4T53u4PdgsXqKaIctwF8ifXlRTTmEPJ8iEPWFdGZvcf7sbwYo6FKFEX9eNNAnzFZ7EzJAQ3CJeOtCRA4rDp7Pw==} @@ -8563,6 +8807,7 @@ packages: /camelcase@6.3.0: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} + dev: true /caniuse-lite@1.0.30001565: resolution: {integrity: sha512-xrE//a3O7TP0vaJ8ikzkD2c2NgcVUvsEe2IvFTntV4Yd1Z9FVzh+gW+enX96L0psrbaFMcVcH2l90xNuGDWc8w==} @@ -8572,10 +8817,6 @@ packages: hasBin: true dev: false - /caseless@0.12.0: - resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==} - dev: false - /chalk@2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} engines: {node: '>=4'} @@ -8639,13 +8880,6 @@ packages: engines: {node: '>=6.0'} dev: false - /chrono-node@2.7.3: - resolution: {integrity: sha512-M/CusGocGJaubS8OFPEzmSa6IT/MJo2LaVqFyUVaLMo+UWwqyahKHsDe9FQBzwaytVGwR/bwZ5JhnAcu894Owg==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - dayjs: 1.11.10 - dev: false - /ci-info@2.0.0: resolution: {integrity: sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==} dev: true @@ -8708,13 +8942,6 @@ packages: yargs: 15.4.1 dev: false - /cli-progress@3.12.0: - resolution: {integrity: sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==} - engines: {node: '>=4'} - dependencies: - string-width: 4.2.3 - dev: false - /cli-spinners@2.9.2: resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} engines: {node: '>=6'} @@ -8797,18 +9024,6 @@ packages: engines: {node: '>=0.10.0'} dev: false - /codesandbox-import-util-types@2.2.3: - resolution: {integrity: sha512-Qj00p60oNExthP2oR3vvXmUGjukij+rxJGuiaKM6tyUmSyimdZsqHI/TUvFFClAffk9s7hxGnQgWQ8KCce27qQ==} - dev: false - - /codesandbox-import-utils@2.2.3: - resolution: {integrity: sha512-ymtmcgZKU27U+nM2qUb21aO8Ut/u2S9s6KorOgG81weP+NA0UZkaHKlaRqbLJ9h4i/4FLvwmEXYAnTjNmp6ogg==} - dependencies: - codesandbox-import-util-types: 2.2.3 - istextorbinary: 2.6.0 - lz-string: 1.5.0 - dev: false - /collect-v8-coverage@1.0.2: resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==} dev: true @@ -8830,11 +9045,6 @@ packages: /color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - /color-support@1.1.3: - resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} - hasBin: true - dev: false - /colors@1.0.3: resolution: {integrity: sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==} engines: {node: '>=0.1.90'} @@ -8990,6 +9200,7 @@ packages: /convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + dev: true /cookie-signature@1.0.6: resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} @@ -9037,16 +9248,13 @@ packages: resolution: {integrity: sha512-cNzGqFsh3Ot+529GIXacjTJ7kegdt5fPXxCBVS1G0iaZpuo/tBz399ymceLJveQhFFZ8qThHiP3fzuoQjKN2ow==} dependencies: browserslist: 4.22.1 + dev: true /core-js@3.33.3: resolution: {integrity: sha512-lo0kOocUlLKmm6kv/FswQL8zbkH7mVsLJ/FULClOhv8WRVmKLVcs6XPNQAzstfeJTCHMyButEwG+z1kHxHoDZw==} requiresBuild: true dev: false - /core-util-is@1.0.2: - resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==} - dev: false - /core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} @@ -9084,14 +9292,6 @@ packages: /create-require@1.1.1: resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} - /cron-parser@3.5.0: - resolution: {integrity: sha512-wyVZtbRs6qDfFd8ap457w3XVntdvqcwBGxBoTvJQH9KGVKL/fB+h2k3C8AqiVxvUQKN1Ps/Ns46CNViOpVDhfQ==} - engines: {node: '>=0.8'} - dependencies: - is-nan: 1.3.2 - luxon: 1.28.1 - dev: false - /cron-time-generator@1.3.2: resolution: {integrity: sha512-GpbDPMAakb1jaHAS1HeH/9lC1wvNavpAQ2pyndA27/G5FO5iA0y29rKR4Bnmzra5Kc2cX79jY2M7wckDzkhINA==} dev: false @@ -9173,15 +9373,6 @@ packages: engines: {node: '>= 6'} dev: false - /csv-write-stream@2.0.0: - resolution: {integrity: sha512-QTraH6FOYfM5f+YGwx71hW1nR9ZjlWri67/D4CWtiBkdce0UAa91Vc0yyHg0CjC0NeEGnvO/tBSJkA1XF9D9GQ==} - hasBin: true - dependencies: - argparse: 1.0.10 - generate-object-property: 1.2.0 - ndjson: 1.5.0 - dev: false - /culvert@0.1.2: resolution: {integrity: sha512-yi1x3EAWKjQTreYWeSd98431AV+IEE0qoDyOoaHJ7KJ21gv6HtBXHVLX74opVSGqcR8/AbjJBHAHpcOy2bj5Gg==} dev: false @@ -9193,13 +9384,6 @@ packages: type: 1.2.0 dev: false - /dashdash@1.14.1: - resolution: {integrity: sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==} - engines: {node: '>=0.10'} - dependencies: - assert-plus: 1.0.0 - dev: false - /data-uri-to-buffer@6.0.1: resolution: {integrity: sha512-MZd3VlchQkp8rdend6vrx7MmVDJzSNTBvghvKjirLkD+WTChA3KUf0jkE68Q4UyctNqI11zZO9/x2Yx+ub5Cvg==} engines: {node: '>= 14'} @@ -9314,59 +9498,6 @@ packages: mimic-response: 1.0.1 dev: true - /decompress-tar@4.1.1: - resolution: {integrity: sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==} - engines: {node: '>=4'} - dependencies: - file-type: 5.2.0 - is-stream: 1.1.0 - tar-stream: 1.6.2 - dev: false - - /decompress-tarbz2@4.1.1: - resolution: {integrity: sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==} - engines: {node: '>=4'} - dependencies: - decompress-tar: 4.1.1 - file-type: 6.2.0 - is-stream: 1.1.0 - seek-bzip: 1.0.6 - unbzip2-stream: 1.4.3 - dev: false - - /decompress-targz@4.1.1: - resolution: {integrity: sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==} - engines: {node: '>=4'} - dependencies: - decompress-tar: 4.1.1 - file-type: 5.2.0 - is-stream: 1.1.0 - dev: false - - /decompress-unzip@4.0.1: - resolution: {integrity: sha512-1fqeluvxgnn86MOh66u8FjbtJpAFv5wgCT9Iw8rcBqQcCo5tO8eiJw7NNTrvt9n4CRBVq7CstiS922oPgyGLrw==} - engines: {node: '>=4'} - dependencies: - file-type: 3.9.0 - get-stream: 2.3.1 - pify: 2.3.0 - yauzl: 2.10.0 - dev: false - - /decompress@4.2.1: - resolution: {integrity: sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ==} - engines: {node: '>=4'} - dependencies: - decompress-tar: 4.1.1 - decompress-tarbz2: 4.1.1 - decompress-targz: 4.1.1 - decompress-unzip: 4.0.1 - graceful-fs: 4.2.11 - make-dir: 1.3.0 - pify: 2.3.0 - strip-dirs: 2.1.0 - dev: false - /dedent@1.5.1: resolution: {integrity: sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==} peerDependencies: @@ -9440,6 +9571,7 @@ packages: define-data-property: 1.1.1 has-property-descriptors: 1.0.1 object-keys: 1.1.1 + dev: true /degenerator@5.0.1: resolution: {integrity: sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==} @@ -9450,20 +9582,6 @@ packages: esprima: 4.0.1 dev: false - /del@6.1.1: - resolution: {integrity: sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==} - engines: {node: '>=10'} - dependencies: - globby: 11.1.0 - graceful-fs: 4.2.11 - is-glob: 4.0.3 - is-path-cwd: 2.2.0 - is-path-inside: 3.0.3 - p-map: 4.0.0 - rimraf: 3.0.2 - slash: 3.0.0 - dev: false - /delay@5.0.0: resolution: {integrity: sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==} engines: {node: '>=10'} @@ -9477,11 +9595,6 @@ packages: resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} dev: false - /denque@1.5.1: - resolution: {integrity: sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==} - engines: {node: '>=0.10'} - dev: false - /depd@1.1.2: resolution: {integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==} engines: {node: '>= 0.6'} @@ -9510,11 +9623,6 @@ packages: hasBin: true dev: false - /detect-libc@2.0.2: - resolution: {integrity: sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==} - engines: {node: '>=8'} - dev: false - /detect-newline@3.1.0: resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} engines: {node: '>=8'} @@ -9685,27 +9793,12 @@ packages: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} dev: false - /ecc-jsbn@0.1.2: - resolution: {integrity: sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==} - dependencies: - jsbn: 0.1.1 - safer-buffer: 2.1.2 - dev: false - /ecdsa-sig-formatter@1.0.11: resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} dependencies: safe-buffer: 5.2.1 dev: false - /editions@2.3.1: - resolution: {integrity: sha512-ptGvkwTvGdGfC0hfhKg0MT+TRLRKGtUiWGBInxOm5pz7ssADezahjCUaYuZ8Dr+C05FW0AECIIPt4WBxVINEhA==} - engines: {node: '>=0.8'} - dependencies: - errlop: 2.2.0 - semver: 6.3.1 - dev: false - /editor@1.0.0: resolution: {integrity: sha512-SoRmbGStwNYHgKfjOrX2L0mUvp9bUVv0uPppZSOMAntEbcFtoC3MKF5b3T6HQPXKIV+QGY3xPO3JK5it5lVkuw==} dev: true @@ -9728,18 +9821,6 @@ packages: /electron-to-chromium@1.4.597: resolution: {integrity: sha512-0XOQNqHhg2YgRVRUrS4M4vWjFCFIP2ETXcXe/0KIQBjXE9Cpy+tgzzYfuq6HGai3hWq0YywtG+5XK8fyG08EjA==} - /elliptic@6.5.4: - resolution: {integrity: sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==} - dependencies: - bn.js: 4.12.0 - brorand: 1.1.0 - hash.js: 1.1.7 - hmac-drbg: 1.0.1 - inherits: 2.0.4 - minimalistic-assert: 1.0.1 - minimalistic-crypto-utils: 1.0.1 - dev: false - /emitter-listener@1.1.2: resolution: {integrity: sha512-Bt1sBAGFHY9DKY+4/2cV6izcKJUf5T7/gkdmkxzX/qv9CcGH8xSwVRW5mtX03SWJtRTWSOpzCuWN9rBFYZepZQ==} dependencies: @@ -9828,7 +9909,7 @@ packages: dependencies: '@types/cookie': 0.4.1 '@types/cors': 2.8.17 - '@types/node': 20.10.1 + '@types/node': 20.10.7 accepts: 1.3.8 base64id: 2.0.0 cookie: 0.4.2 @@ -9877,11 +9958,6 @@ packages: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} - /env-var@6.3.0: - resolution: {integrity: sha512-gaNzDZuVaJQJlP2SigAZLu/FieZN5MzdN7lgHNehESwlRanHwGQ/WUtJ7q//dhrj3aGBZM45yEaKOuvSJaf4mA==} - engines: {node: '>=8'} - dev: false - /erlpack@0.1.4: resolution: {integrity: sha512-CJYbkEvsB5FqCCu2tLxF1eYKi28PvemC12oqzJ9oO6mDFrFO9G9G7nNJUHhiAyyL9zfXTOJx/tOcrQk+ncD65w==} requiresBuild: true @@ -9894,11 +9970,6 @@ packages: resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==} dev: false - /errlop@2.2.0: - resolution: {integrity: sha512-e64Qj9+4aZzjzzFpZC7p5kmm/ccCrbLhAJplhsDXQFs87XTsXwOpH4s1Io2s90Tau/8r2j9f4l/thhDevRjzxw==} - engines: {node: '>=0.8'} - dev: false - /error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} dependencies: @@ -9984,14 +10055,6 @@ packages: is-symbol: 1.0.4 dev: true - /es5-ext@0.10.53: - resolution: {integrity: sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==} - dependencies: - es6-iterator: 2.0.3 - es6-symbol: 3.1.3 - next-tick: 1.0.0 - dev: false - /es5-ext@0.10.62: resolution: {integrity: sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==} engines: {node: '>=0.10'} @@ -10443,20 +10506,6 @@ packages: jest-util: 29.7.0 dev: true - /express-graphql@0.12.0(graphql@15.8.0): - resolution: {integrity: sha512-DwYaJQy0amdy3pgNtiTDuGGM2BLdj+YO2SgbKoLliCfuHv3VVTt7vNG/ZqK2hRYjtYHE2t2KB705EU94mE64zg==} - engines: {node: '>= 10.x'} - deprecated: This package is no longer maintained. We recommend using `graphql-http` instead. Please consult the migration document https://github.com/graphql/graphql-http#migrating-express-grpahql. - peerDependencies: - graphql: ^14.7.0 || ^15.3.0 - dependencies: - accepts: 1.3.8 - content-type: 1.0.5 - graphql: 15.8.0 - http-errors: 1.8.0 - raw-body: 2.5.2 - dev: false - /express-rate-limit@6.5.1(express@4.17.1): resolution: {integrity: sha512-pxO6ioBLd3i8IHL+RmJtL4noYzte5fugoMdaDabtU4hcg53+x0QkTwfPtM7vWD0YUaXQgNj9NRdzmps+CHEHlA==} engines: {node: '>= 12.9.0'} @@ -10560,11 +10609,6 @@ packages: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} dev: false - /extsprintf@1.3.0: - resolution: {integrity: sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==} - engines: {'0': node >=0.6.0} - dev: false - /fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} @@ -10631,33 +10675,12 @@ packages: resolution: {integrity: sha512-GDqVQezKzRABdeqflsgMr7ktzgF9CyS+p2oe0jJqUY6izSSbhPIQJDpoU4PtGcD7VPM9xh/dVrTu6z1nwgmEGw==} dev: false - /fd-slicer@1.1.0: - resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} - dependencies: - pend: 1.2.0 - dev: false - /file-entry-cache@6.0.1: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} dependencies: flat-cache: 3.2.0 - /file-type@3.9.0: - resolution: {integrity: sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA==} - engines: {node: '>=0.10.0'} - dev: false - - /file-type@5.2.0: - resolution: {integrity: sha512-Iq1nJ6D2+yIO4c8HHg4fyVb8mAJieo1Oloy1mLLaB2PvezNedhBVm+QU7g0qM42aiMbRXTxKKwGD17rjKNJYVQ==} - engines: {node: '>=4'} - dev: false - - /file-type@6.2.0: - resolution: {integrity: sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==} - engines: {node: '>=4'} - dev: false - /file-uri-to-path@1.0.0: resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} dev: false @@ -10733,10 +10756,6 @@ packages: keyv: 4.5.4 rimraf: 3.0.2 - /flatbuffers@23.3.3: - resolution: {integrity: sha512-jmreOaAT1t55keaf+Z259Tvh8tR/Srry9K8dgCgvizhKSEr6gLGgaOJI2WFL5fkOpGOGRZwxUrlFn0GCmXUy6g==} - dev: false - /flatted@3.2.9: resolution: {integrity: sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==} @@ -10766,19 +10785,6 @@ packages: signal-exit: 4.1.0 dev: false - /forever-agent@0.6.1: - resolution: {integrity: sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==} - dev: false - - /form-data@2.3.3: - resolution: {integrity: sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==} - engines: {node: '>= 0.12'} - dependencies: - asynckit: 0.4.0 - combined-stream: 1.0.8 - mime-types: 2.1.35 - dev: false - /form-data@2.5.1: resolution: {integrity: sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==} engines: {node: '>= 0.12'} @@ -10824,10 +10830,6 @@ packages: resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} engines: {node: '>= 0.6'} - /fs-constants@1.0.0: - resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} - dev: false - /fs-extra@4.0.3: resolution: {integrity: sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==} dependencies: @@ -10845,16 +10847,6 @@ packages: universalify: 0.1.2 dev: false - /fs-extra@9.1.0: - resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==} - engines: {node: '>=10'} - dependencies: - at-least-node: 1.0.0 - graceful-fs: 4.2.11 - jsonfile: 6.1.0 - universalify: 2.0.1 - dev: false - /fs-minipass@1.2.7: resolution: {integrity: sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==} dependencies: @@ -10912,21 +10904,6 @@ packages: wide-align: 1.1.5 dev: false - /gauge@3.0.2: - resolution: {integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==} - engines: {node: '>=10'} - dependencies: - aproba: 2.0.0 - color-support: 1.1.3 - console-control-strings: 1.1.0 - has-unicode: 2.0.1 - object-assign: 4.1.1 - signal-exit: 3.0.7 - string-width: 4.2.3 - strip-ansi: 6.0.1 - wide-align: 1.1.5 - dev: false - /gaxios@3.2.0: resolution: {integrity: sha512-+6WPeVzPvOshftpxJwRi2Ozez80tn/hdtOUag7+gajDHRJvAblKxTFSSMPtr2hmnLy7p0mvYz0rMXLBl8pSO7Q==} engines: {node: '>=10'} @@ -10985,12 +10962,6 @@ packages: - supports-color dev: false - /generate-object-property@1.2.0: - resolution: {integrity: sha512-TuOwZWgJ2VAMEGJvAyPWvpqxSANF0LDpmyHauMjFYzaACvn+QTT/AZomvPCzVBV7yDN3OmwHQ5OvHaeLKre3JQ==} - dependencies: - is-property: 1.0.2 - dev: false - /generic-pool@3.9.0: resolution: {integrity: sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==} engines: {node: '>= 4'} @@ -10999,6 +10970,7 @@ packages: /gensync@1.0.0-beta.2: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} + dev: true /get-caller-file@1.0.3: resolution: {integrity: sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==} @@ -11021,14 +10993,6 @@ packages: engines: {node: '>=8.0.0'} dev: true - /get-stream@2.3.1: - resolution: {integrity: sha512-AUGhbbemXxrZJRD5cDvKtQxLuYaIbNtDTK8YqupCI393Q2KSTreEsLUN3ZxAWFGiKTzL6nKuzfcIvieflUX9qA==} - engines: {node: '>=0.10.0'} - dependencies: - object-assign: 4.1.1 - pinkie-promise: 2.0.1 - dev: false - /get-stream@3.0.0: resolution: {integrity: sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==} engines: {node: '>=4'} @@ -11073,12 +11037,6 @@ packages: - supports-color dev: false - /getpass@0.1.7: - resolution: {integrity: sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==} - dependencies: - assert-plus: 1.0.0 - dev: false - /git-node-fs@1.0.0(js-git@0.7.8): resolution: {integrity: sha512-bLQypt14llVXBg0S0u8q8HmU7g9p3ysH+NvVlae5vILuUvs759665HvmR5+wb04KjHyjFcDRxdYb4kyNnluMUQ==} peerDependencies: @@ -11170,6 +11128,7 @@ packages: /globals@11.12.0: resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} engines: {node: '>=4'} + dev: true /globals@13.23.0: resolution: {integrity: sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==} @@ -11255,21 +11214,6 @@ packages: /graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - /graphql-scalars@1.22.4(graphql@15.8.0): - resolution: {integrity: sha512-ILnv7jq5VKHLUyoaTFX7lgYrjCd6vTee9i8/B+D4zJKJT5TguOl0KkpPEbXHjmeor8AZYrVsrYUHdqRBMX1pjA==} - engines: {node: '>=10'} - peerDependencies: - graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 - dependencies: - graphql: 15.8.0 - tslib: 2.6.2 - dev: false - - /graphql@15.8.0: - resolution: {integrity: sha512-5gghUc24tP9HRznNpV2+FIoq3xKkj5dTQqf4v0CpdPbFVwFkWoxOM+o+2OC9ZSvjEMTjfmG9QT+gcvggTwW1zw==} - engines: {node: '>= 10.x'} - dev: false - /gray-matter@4.0.3: resolution: {integrity: sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==} engines: {node: '>=6.0'} @@ -11292,20 +11236,6 @@ packages: - supports-color dev: false - /har-schema@2.0.0: - resolution: {integrity: sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==} - engines: {node: '>=4'} - dev: false - - /har-validator@5.1.5: - resolution: {integrity: sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==} - engines: {node: '>=6'} - deprecated: this library is no longer supported - dependencies: - ajv: 6.12.6 - har-schema: 2.0.0 - dev: false - /has-bigints@1.0.2: resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} dev: true @@ -11351,13 +11281,6 @@ packages: resolution: {integrity: sha512-Gjzu0Xn7IagXVkSu9cSFuK1fqzwtLwFhNhVL8IFJijRNMgUttFbBSIAzKuSIrsFMO1+g1RlsoN49zPIbwPDMGQ==} dev: false - /hash.js@1.1.7: - resolution: {integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==} - dependencies: - inherits: 2.0.4 - minimalistic-assert: 1.0.1 - dev: false - /hasown@2.0.0: resolution: {integrity: sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==} engines: {node: '>= 0.4'} @@ -11398,14 +11321,6 @@ packages: resolution: {integrity: sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==} dev: false - /hmac-drbg@1.0.1: - resolution: {integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==} - dependencies: - hash.js: 1.1.7 - minimalistic-assert: 1.0.1 - minimalistic-crypto-utils: 1.0.1 - dev: false - /hosted-git-info@2.8.9: resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} dev: false @@ -11491,17 +11406,6 @@ packages: toidentifier: 1.0.0 dev: false - /http-errors@1.8.0: - resolution: {integrity: sha512-4I8r0C5JDhT5VkvI47QktDW75rNlGVsUf/8hzjCC/wkWI/jdTRmBb9aI7erSG82r1bjKY3F6k28WnsVxB1C73A==} - engines: {node: '>= 0.6'} - dependencies: - depd: 1.1.2 - inherits: 2.0.4 - setprototypeof: 1.2.0 - statuses: 1.5.0 - toidentifier: 1.0.0 - dev: false - /http-errors@2.0.0: resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} engines: {node: '>= 0.8'} @@ -11513,17 +11417,6 @@ packages: toidentifier: 1.0.1 dev: false - /http-proxy-agent@4.0.1: - resolution: {integrity: sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==} - engines: {node: '>= 6'} - dependencies: - '@tootallnate/once': 1.1.2 - agent-base: 6.0.2 - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - dev: false - /http-proxy-agent@5.0.0: resolution: {integrity: sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==} engines: {node: '>= 6'} @@ -11545,15 +11438,6 @@ packages: - supports-color dev: false - /http-signature@1.2.0: - resolution: {integrity: sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==} - engines: {node: '>=0.8', npm: '>=1.3.7'} - dependencies: - assert-plus: 1.0.0 - jsprim: 1.4.2 - sshpk: 1.18.0 - dev: false - /http2-client@1.3.5: resolution: {integrity: sha512-EC2utToWl4RKfs5zd36Mxq7nzHHBuomZboI0yYL6Y0RmBgT7Sgkq4rQ0ezFTYoIsSs7Tm9SJe+o2FcAg6GBhGA==} dev: true @@ -11594,10 +11478,6 @@ packages: ms: 2.1.3 dev: false - /humps@2.0.1: - resolution: {integrity: sha512-E0eIbrFWUhwfXJmsbdjRQFQPrl5pTEoKlz163j1mTqqUnU9PgR4AgB8AIITzuB3vLBdxZXyZ9TDIrwB2OASz4g==} - dev: false - /iconv-lite@0.4.24: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} engines: {node: '>=0.10.0'} @@ -11719,35 +11599,11 @@ packages: side-channel: 1.0.4 dev: true - /interpret@1.4.0: - resolution: {integrity: sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==} - engines: {node: '>= 0.10'} - dev: false - /invert-kv@1.0.0: resolution: {integrity: sha512-xgs2NH9AE66ucSq4cNG1nhSFghr5l6tdL15Pk+jl46bmmBapgoaY/AacXyaDznAqmGL99TiLSQgO/XazFSKYeQ==} engines: {node: '>=0.10.0'} dev: false - /ioredis@4.28.5: - resolution: {integrity: sha512-3GYo0GJtLqgNXj4YhrisLaNNvWSNwSS2wS4OELGfGxH8I69+XfNdnmV1AyN+ZqMh0i7eX+SWjrwFKDBDgfBC1A==} - engines: {node: '>=6'} - dependencies: - cluster-key-slot: 1.1.2 - debug: 4.3.4 - denque: 1.5.1 - lodash.defaults: 4.2.0 - lodash.flatten: 4.4.0 - lodash.isarguments: 3.1.0 - p-map: 2.1.0 - redis-commands: 1.7.0 - redis-errors: 1.2.0 - redis-parser: 3.0.0 - standard-as-callback: 2.1.0 - transitivePeerDependencies: - - supports-color - dev: false - /ip@1.1.8: resolution: {integrity: sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==} dev: false @@ -11829,6 +11685,7 @@ packages: resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} engines: {node: '>=8'} hasBin: true + dev: true /is-docker@3.0.0: resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} @@ -11909,18 +11766,6 @@ packages: resolution: {integrity: sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==} dev: false - /is-nan@1.3.2: - resolution: {integrity: sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.5 - define-properties: 1.2.1 - dev: false - - /is-natural-number@4.0.1: - resolution: {integrity: sha512-Y4LTamMe0DDQIIAlaer9eKebAlDSV6huy+TWhJVPlzZh2o4tRP5SQWFlLn5N0To4mDD22/qdOq+veo1cSISLgQ==} - dev: false - /is-negative-zero@2.0.2: resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} engines: {node: '>= 0.4'} @@ -11951,11 +11796,6 @@ packages: resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==} engines: {node: '>=8'} - /is-path-cwd@2.2.0: - resolution: {integrity: sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==} - engines: {node: '>=6'} - dev: false - /is-path-inside@3.0.3: resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} engines: {node: '>=8'} @@ -11969,10 +11809,6 @@ packages: resolution: {integrity: sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==} dev: false - /is-property@1.0.2: - resolution: {integrity: sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==} - dev: false - /is-regex@1.1.4: resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} engines: {node: '>= 0.4'} @@ -12084,10 +11920,6 @@ packages: form-data: 2.5.1 dev: false - /isstream@0.1.2: - resolution: {integrity: sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==} - dev: false - /istanbul-lib-coverage@3.2.0: resolution: {integrity: sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==} engines: {node: '>=8'} @@ -12152,19 +11984,6 @@ packages: istanbul-lib-report: 3.0.1 dev: true - /istextorbinary@2.6.0: - resolution: {integrity: sha512-+XRlFseT8B3L9KyjxxLjfXSLMuErKDsd8DBNrsaxoViABMEZlOSCstwmw0qpoFX3+U6yWU1yhLudAe6/lETGGA==} - engines: {node: '>=0.12'} - dependencies: - binaryextensions: 2.3.0 - editions: 2.3.1 - textextensions: 2.6.0 - dev: false - - /iterall@1.3.0: - resolution: {integrity: sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg==} - dev: false - /iterate-object@1.3.4: resolution: {integrity: sha512-4dG1D1x/7g8PwHS9aK6QV5V94+ZvyP4+d19qDv43EzImmrndysIl4prmJ1hWWIGCqrZHyaHBm6BSEWHOLnpoNw==} dev: false @@ -12206,7 +12025,7 @@ packages: '@jest/expect': 29.7.0 '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.10.1 + '@types/node': 20.10.7 chalk: 4.1.2 co: 4.6.0 dedent: 1.5.1 @@ -12296,7 +12115,7 @@ packages: - supports-color dev: true - /jest-config@29.7.0(@types/node@20.10.1)(ts-node@10.6.0): + /jest-config@29.7.0(@types/node@20.10.7)(ts-node@10.6.0): resolution: {integrity: sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} peerDependencies: @@ -12311,7 +12130,7 @@ packages: '@babel/core': 7.23.5 '@jest/test-sequencer': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.10.1 + '@types/node': 20.10.7 babel-jest: 29.7.0(@babel/core@7.23.5) chalk: 4.1.2 ci-info: 3.9.0 @@ -12371,7 +12190,7 @@ packages: '@jest/environment': 29.7.0 '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.10.1 + '@types/node': 20.10.7 jest-mock: 29.7.0 jest-util: 29.7.0 dev: true @@ -12387,7 +12206,7 @@ packages: dependencies: '@jest/types': 29.6.3 '@types/graceful-fs': 4.1.9 - '@types/node': 20.10.1 + '@types/node': 20.10.7 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -12438,7 +12257,7 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@jest/types': 29.6.3 - '@types/node': 20.10.1 + '@types/node': 20.10.7 jest-util: 29.7.0 dev: true @@ -12493,7 +12312,7 @@ packages: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.10.1 + '@types/node': 20.10.7 chalk: 4.1.2 emittery: 0.13.1 graceful-fs: 4.2.11 @@ -12524,7 +12343,7 @@ packages: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.10.1 + '@types/node': 20.10.7 chalk: 4.1.2 cjs-module-lexer: 1.2.3 collect-v8-coverage: 1.0.2 @@ -12576,7 +12395,7 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@jest/types': 29.6.3 - '@types/node': 20.10.1 + '@types/node': 20.10.7 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -12601,7 +12420,7 @@ packages: dependencies: '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.10.1 + '@types/node': 20.10.7 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.13.1 @@ -12613,7 +12432,7 @@ packages: resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} engines: {node: '>= 10.13.0'} dependencies: - '@types/node': 20.10.1 + '@types/node': 20.10.7 merge-stream: 2.0.0 supports-color: 8.1.1 dev: false @@ -12622,7 +12441,7 @@ packages: resolution: {integrity: sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@types/node': 20.10.1 + '@types/node': 20.10.7 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -12654,16 +12473,6 @@ packages: engines: {node: '>= 0.6.0'} dev: false - /joi@17.11.0: - resolution: {integrity: sha512-NgB+lZLNoqISVy1rZocE9PZI36bL/77ie924Ri43yEvi9GUUMPeyVIr8KdFTMUlby1p0PBYMk9spIxEUQYqrJQ==} - dependencies: - '@hapi/hoek': 9.3.0 - '@hapi/topo': 5.1.0 - '@sideway/address': 4.1.4 - '@sideway/formula': 3.0.1 - '@sideway/pinpoint': 2.0.0 - dev: false - /join-component@1.1.0: resolution: {integrity: sha512-bF7vcQxbODoGK1imE2P9GS9aw4zD0Sd+Hni68IMZLj7zRnquH7dXUmMw9hDI5S/Jzt7q+IyTXN0rSg2GI0IKhQ==} dev: false @@ -12698,6 +12507,7 @@ packages: /js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + dev: true /js-yaml@3.14.1: resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} @@ -12713,18 +12523,16 @@ packages: dependencies: argparse: 2.0.1 - /jsbn@0.1.1: - resolution: {integrity: sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==} - dev: false - /jsesc@0.5.0: resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} hasBin: true + dev: true /jsesc@2.5.2: resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} engines: {node: '>=4'} hasBin: true + dev: true /json-bigint@1.0.0: resolution: {integrity: sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==} @@ -12748,16 +12556,14 @@ packages: /json-schema-traverse@1.0.0: resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} - /json-schema@0.4.0: - resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} - dev: false - /json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} /json-stringify-safe@5.0.1: resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} + requiresBuild: true dev: false + optional: true /json-to-ast@2.1.0: resolution: {integrity: sha512-W9Lq347r8tA1DfMvAGn9QNcgYm4Wm7Yc+k8e6vezpMnRT+NHbtlxgNBXRVjXe9YM6eTn6+p/MKOlV/aABJcSnQ==} @@ -12796,14 +12602,6 @@ packages: graceful-fs: 4.2.11 dev: false - /jsonfile@6.1.0: - resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} - dependencies: - universalify: 2.0.1 - optionalDependencies: - graceful-fs: 4.2.11 - dev: false - /jsonparse@1.3.1: resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} engines: {'0': node >= 0.2.0} @@ -12846,16 +12644,6 @@ packages: semver: 7.5.4 dev: false - /jsprim@1.4.2: - resolution: {integrity: sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==} - engines: {node: '>=0.6.0'} - dependencies: - assert-plus: 1.0.0 - extsprintf: 1.3.0 - json-schema: 0.4.0 - verror: 1.10.0 - dev: false - /jwa@1.4.1: resolution: {integrity: sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==} dependencies: @@ -12872,14 +12660,6 @@ packages: safe-buffer: 5.2.1 dev: false - /jwk-to-pem@2.0.5: - resolution: {integrity: sha512-L90jwellhO8jRKYwbssU9ifaMVqajzj3fpRjDKcsDzrslU9syRbFqfkXtT4B89HYAap+xsxNcxgBSB09ig+a7A==} - dependencies: - asn1.js: 5.4.1 - elliptic: 6.5.4 - safe-buffer: 5.2.1 - dev: false - /jwks-rsa@3.1.0: resolution: {integrity: sha512-v7nqlfezb9YfHHzYII3ef2a2j1XnGeSE/bK3WfumaYCqONAIstJbrEGapz4kadScZzEt7zYCN7bucj8C0Mv/Rg==} engines: {node: '>=14'} @@ -13026,14 +12806,7 @@ packages: /lodash.debounce@4.0.8: resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} - - /lodash.defaults@4.2.0: - resolution: {integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==} - dev: false - - /lodash.flatten@4.4.0: - resolution: {integrity: sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==} - dev: false + dev: true /lodash.get@4.4.2: resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==} @@ -13043,10 +12816,6 @@ packages: resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==} dev: false - /lodash.isarguments@3.1.0: - resolution: {integrity: sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==} - dev: false - /lodash.isboolean@3.0.3: resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==} dev: false @@ -13168,6 +12937,7 @@ packages: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} dependencies: yallist: 3.1.1 + dev: true /lru-cache@6.0.0: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} @@ -13198,30 +12968,14 @@ packages: es5-ext: 0.10.62 dev: false - /luxon@1.28.1: - resolution: {integrity: sha512-gYHAa180mKrNIUJCbwpmD0aTu9kV0dREDrwNnuyFAsO1Wt0EVYSZelPnJlbj9HplzXX/YWXHFTL45kvZ53M0pw==} - dev: false - /luxon@3.3.0: resolution: {integrity: sha512-An0UCfG/rSiqtAIiBPO0Y9/zAnHUZxAMiCpTd5h2smgsj7GGmcenvrvww2cqNA8/4A5ZrD1gJpHN2mIHZQF+Mg==} engines: {node: '>=12'} - /lz-string@1.5.0: - resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} - hasBin: true - dev: false - /magic-bytes.js@1.5.0: resolution: {integrity: sha512-wJkXvutRbNWcc37tt5j1HyOK1nosspdh3dj6LUYYAvF6JYNqs53IfRvK9oEpcwiDA1NdoIi64yAMfdivPeVAyw==} dev: false - /make-dir@1.3.0: - resolution: {integrity: sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==} - engines: {node: '>=4'} - dependencies: - pify: 3.0.0 - dev: false - /make-dir@3.1.0: resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} engines: {node: '>=8'} @@ -13379,14 +13133,6 @@ packages: engines: {node: '>=4'} dev: true - /minimalistic-assert@1.0.1: - resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} - dev: false - - /minimalistic-crypto-utils@1.0.1: - resolution: {integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==} - dev: false - /minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} dependencies: @@ -13509,15 +13255,6 @@ packages: resolution: {integrity: sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==} dev: false - /moment-range@4.0.2(moment@2.29.4): - resolution: {integrity: sha512-n8sceWwSTjmz++nFHzeNEUsYtDqjgXgcOBzsHi+BoXQU2FW+eU92LUaK8gqOiSu5PG57Q9sYj1Fz4LRDj4FtKA==} - peerDependencies: - moment: '>= 2' - dependencies: - es6-symbol: 3.1.3 - moment: 2.29.4 - dev: false - /moment-timezone@0.5.43: resolution: {integrity: sha512-72j3aNyuIsDxdF1i7CEgV2FfxM1r6aaqJyLB2vwb33mXYyoyLly+F1zbWqhA3/bVIoJ4szlUoMbUnVdid32NUQ==} dependencies: @@ -13607,16 +13344,6 @@ packages: hasBin: true dev: false - /ndjson@1.5.0: - resolution: {integrity: sha512-hUPLuaziboGjNF7wHngkgVc0FOclR8dDk/HfEvTtDr/iUrqBWiRcRSTK3/nLOqKH33th714BrMmTPtObI9gZxQ==} - hasBin: true - dependencies: - json-stringify-safe: 5.0.1 - minimist: 1.2.8 - split2: 2.2.0 - through2: 2.0.5 - dev: false - /nearley@2.20.1: resolution: {integrity: sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==} hasBin: true @@ -13664,24 +13391,10 @@ packages: engines: {node: '>= 0.4.0'} dev: false - /next-tick@1.0.0: - resolution: {integrity: sha512-mc/caHeUcdjnC/boPWJefDr4KUIWQNv+tlnFnJd38QMou86QtxQzBJfxgGRzvx8jazYRqrVlaHarfO72uNxPOg==} - dev: false - /next-tick@1.1.0: resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==} dev: false - /nexus@1.3.0(graphql@15.8.0): - resolution: {integrity: sha512-w/s19OiNOs0LrtP7pBmD9/FqJHvZLmCipVRt6v1PM8cRUYIbhEswyNKGHVoC4eHZGPSnD+bOf5A3+gnbt0A5/A==} - peerDependencies: - graphql: 15.x || 16.x - dependencies: - graphql: 15.8.0 - iterall: 1.3.0 - tslib: 2.6.2 - dev: false - /node-abort-controller@3.1.1: resolution: {integrity: sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==} dev: false @@ -13694,10 +13407,6 @@ packages: resolution: {integrity: sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==} dev: false - /node-dijkstra@2.5.0: - resolution: {integrity: sha512-2REYb1lo8yDRAY1gsdhjwQdGVSh47VI5Z5wS8sCqydO/P1OVAKOwLuV1fDxNLvbrtMspW7k2UZ2JKIKP06hl+A==} - dev: false - /node-fetch-h2@2.3.0: resolution: {integrity: sha512-ofRW94Ab0T4AOh5Fk8t0h8OBWrmjb0SSB20xh1H8YnPV9EJ+f5AMoYSUQ2zgJ4Iq2HAK0I2l5/Nequ8YzFS3Hg==} engines: {node: 4.x || >=6.0.0} @@ -13862,15 +13571,7 @@ packages: hasBin: true dependencies: abbrev: 1.1.1 - osenv: 0.1.5 - dev: false - - /nopt@5.0.0: - resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==} - engines: {node: '>=6'} - hasBin: true - dependencies: - abbrev: 1.1.1 + osenv: 0.1.5 dev: false /nopt@7.2.0: @@ -13947,15 +13648,6 @@ packages: set-blocking: 2.0.0 dev: false - /npmlog@5.0.1: - resolution: {integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==} - dependencies: - are-we-there-yet: 2.0.0 - console-control-strings: 1.1.0 - gauge: 3.0.2 - set-blocking: 2.0.0 - dev: false - /nssocket@0.6.0: resolution: {integrity: sha512-a9GSOIql5IqgWJR3F/JXG4KpJTA3Z53Cj0MeMvGpglytB1nxE4PdFNC0jINe27CS7cGivoynwc054EzCcT3M3w==} engines: {node: '>= 0.10.x'} @@ -14030,10 +13722,6 @@ packages: yaml: 1.10.2 dev: true - /oauth-sign@0.9.0: - resolution: {integrity: sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==} - dev: false - /oauth@0.9.15: resolution: {integrity: sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA==} dev: false @@ -14053,6 +13741,7 @@ packages: /object-keys@1.1.1: resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} engines: {node: '>= 0.4'} + dev: true /object.assign@4.1.4: resolution: {integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==} @@ -14298,11 +13987,6 @@ packages: dependencies: p-limit: 3.1.0 - /p-map@2.1.0: - resolution: {integrity: sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==} - engines: {node: '>=6'} - dev: false - /p-map@4.0.0: resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} engines: {node: '>=10'} @@ -14601,12 +14285,8 @@ packages: resolution: {integrity: sha512-XIxfHpEuSJbITd1H3EeQwpcZbTLHc+VVr8ANI9t5sit565tsI4/xK3KWTUFE2e6QiangUkh3B0jihzmGnNrRsQ==} dev: false - /pend@1.2.0: - resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} - dev: false - - /peopledatalabs@5.1.0: - resolution: {integrity: sha512-SlSzDGYec5X2Gpq2rdpzmC7sVDyQneiEzxUconujTGIdsK43zHY03sRrVUhX9IkjkSH4hHGA3/7GLtLKFsUwgQ==} + /peopledatalabs@6.1.5: + resolution: {integrity: sha512-yIXxamojsUcC14hoTvGSrJGD/upgOAJ0sinjznzKAP0ftQEXTz9XDkq/QpKDFLnMVz0asWTHm3CcIVe8P3r0gQ==} dependencies: axios: 1.6.2 copy-anything: 3.0.5 @@ -14614,10 +14294,6 @@ packages: - debug dev: false - /performance-now@2.1.0: - resolution: {integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==} - dev: false - /pg-cloudflare@1.1.1: resolution: {integrity: sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==} requiresBuild: true @@ -14727,23 +14403,6 @@ packages: engines: {node: '>=0.10.0'} dev: false - /pify@3.0.0: - resolution: {integrity: sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==} - engines: {node: '>=4'} - dev: false - - /pinkie-promise@2.0.1: - resolution: {integrity: sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==} - engines: {node: '>=0.10.0'} - dependencies: - pinkie: 2.0.4 - dev: false - - /pinkie@2.0.4: - resolution: {integrity: sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==} - engines: {node: '>=0.10.0'} - dev: false - /pirates@4.0.6: resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} engines: {node: '>= 6'} @@ -14947,10 +14606,6 @@ packages: retry: 0.12.0 dev: false - /promise-timeout@1.3.0: - resolution: {integrity: sha512-5yANTE0tmi5++POym6OgtFmwfDvOXABD9oj/jLQr5GPEyuNEb7jH4wbbANJceJid49jwhi1RddxnhnEAb/doqg==} - dev: false - /promptly@2.2.0: resolution: {integrity: sha512-aC9j+BZsRSSzEsXBNBwDnAxujdx19HycZoKgRgzWnS8eOHg1asuf9heuLprfbe739zY3IdUQx+Egv6Jn135WHA==} dependencies: @@ -14991,7 +14646,7 @@ packages: '@protobufjs/path': 1.1.2 '@protobufjs/pool': 1.1.0 '@protobufjs/utf8': 1.1.0 - '@types/node': 20.10.1 + '@types/node': 20.10.7 long: 5.2.3 dev: false @@ -15081,11 +14736,6 @@ packages: dependencies: side-channel: 1.0.4 - /qs@6.5.3: - resolution: {integrity: sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==} - engines: {node: '>=0.6'} - dev: false - /qs@6.7.0: resolution: {integrity: sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==} engines: {node: '>=0.6'} @@ -15097,12 +14747,6 @@ packages: deprecated: The querystring API is considered Legacy. new code should use the URLSearchParams API instead. dev: false - /querystring@0.2.1: - resolution: {integrity: sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg==} - engines: {node: '>=0.4.x'} - deprecated: The querystring API is considered Legacy. new code should use the URLSearchParams API instead. - dev: false - /queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} @@ -15266,39 +14910,6 @@ packages: dependencies: picomatch: 2.3.1 - /rechoir@0.6.2: - resolution: {integrity: sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==} - engines: {node: '>= 0.10'} - dependencies: - resolve: 1.22.8 - dev: false - - /redis-commands@1.7.0: - resolution: {integrity: sha512-nJWqw3bTFy21hX/CPKHth6sfhZbdiHP6bTawSgQBlKOVRG7EZkfHbbHwQJnrE4vsQf0CMNE+3gJ4Fmm16vdVlQ==} - dev: false - - /redis-errors@1.2.0: - resolution: {integrity: sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==} - engines: {node: '>=4'} - dev: false - - /redis-parser@3.0.0: - resolution: {integrity: sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==} - engines: {node: '>=4'} - dependencies: - redis-errors: 1.2.0 - dev: false - - /redis@3.1.2: - resolution: {integrity: sha512-grn5KoZLr/qrRQVwoSkmzdbw6pwF+/rwODtrOr6vuBRiR/f3rjSTGupbF90Zpqm2oenix8Do6RV7pYEkGwlKkw==} - engines: {node: '>=10'} - dependencies: - denque: 1.5.1 - redis-commands: 1.7.0 - redis-errors: 1.2.0 - redis-parser: 3.0.0 - dev: false - /redis@4.6.11: resolution: {integrity: sha512-kg1Lt4NZLYkAjPOj/WcyIGWfZfnyfKo1Wg9YKVSlzhFwxpFIl3LYI8BWy1Ab963LLDsTz2+OwdsesHKljB3WMQ==} dependencies: @@ -15323,9 +14934,11 @@ packages: engines: {node: '>=4'} dependencies: regenerate: 1.4.2 + dev: true /regenerate@1.4.2: resolution: {integrity: sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==} + dev: true /regenerator-runtime@0.14.0: resolution: {integrity: sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==} @@ -15334,6 +14947,7 @@ packages: resolution: {integrity: sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==} dependencies: '@babel/runtime': 7.23.5 + dev: true /regexp.prototype.flags@1.5.1: resolution: {integrity: sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==} @@ -15354,6 +14968,7 @@ packages: regjsparser: 0.9.1 unicode-match-property-ecmascript: 2.0.0 unicode-match-property-value-ecmascript: 2.1.0 + dev: true /registry-auth-token@4.2.2: resolution: {integrity: sha512-PC5ZysNb42zpFME6D/XlIgtNGdTl8bBOCw90xQLVMpzuuubJKYDWFAEuUNc+Cn8Z8724tg2SDhDRrkVEsqfDMg==} @@ -15374,62 +14989,12 @@ packages: hasBin: true dependencies: jsesc: 0.5.0 + dev: true /remove-trailing-slash@0.1.1: resolution: {integrity: sha512-o4S4Qh6L2jpnCy83ysZDau+VORNvnFw07CKSAymkd6ICNVEPisMyzlc00KlvvicsxKck94SEwhDnMNdICzO+tA==} dev: false - /request-promise-core@1.1.4(request@2.88.2): - resolution: {integrity: sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==} - engines: {node: '>=0.10.0'} - peerDependencies: - request: ^2.34 - dependencies: - lodash: 4.17.21 - request: 2.88.2 - dev: false - - /request-promise@4.2.6(request@2.88.2): - resolution: {integrity: sha512-HCHI3DJJUakkOr8fNoCc73E5nU5bqITjOYFMDrKHYOXWXrgD/SBaC7LjwuPymUprRyuF06UK7hd/lMHkmUXglQ==} - engines: {node: '>=0.10.0'} - deprecated: request-promise has been deprecated because it extends the now deprecated request package, see https://github.com/request/request/issues/3142 - peerDependencies: - request: ^2.34 - dependencies: - bluebird: 3.7.2 - request: 2.88.2 - request-promise-core: 1.1.4(request@2.88.2) - stealthy-require: 1.1.1 - tough-cookie: 2.5.0 - dev: false - - /request@2.88.2: - resolution: {integrity: sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==} - engines: {node: '>= 6'} - deprecated: request has been deprecated, see https://github.com/request/request/issues/3142 - dependencies: - aws-sign2: 0.7.0 - aws4: 1.12.0 - caseless: 0.12.0 - combined-stream: 1.0.8 - extend: 3.0.2 - forever-agent: 0.6.1 - form-data: 2.3.3 - har-validator: 5.1.5 - http-signature: 1.2.0 - is-typedarray: 1.0.0 - isstream: 0.1.2 - json-stringify-safe: 5.0.1 - mime-types: 2.1.35 - oauth-sign: 0.9.0 - performance-now: 2.1.0 - qs: 6.5.3 - safe-buffer: 5.2.1 - tough-cookie: 2.5.0 - tunnel-agent: 0.6.0 - uuid: 3.4.0 - dev: false - /require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} @@ -15659,13 +15224,6 @@ packages: resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==} dev: false - /seek-bzip@1.0.6: - resolution: {integrity: sha512-e1QtP3YL5tWww8uKaOCQ18UxIT2laNBXHjV/S2WYCiK4udiv8lkG89KRIoCjUagnAmCBurjF4zEVX2ByBbnCjQ==} - hasBin: true - dependencies: - commander: 2.20.3 - dev: false - /selderee@0.11.0: resolution: {integrity: sha512-5TF+l7p4+OsnP8BCCvSyZiSPc4x4//p5uPwK8TCnVPJYRmU2aYKMpOXvw8zM5a5JvuuCGN1jmsMwuU2W02ukfA==} dependencies: @@ -15904,16 +15462,6 @@ packages: resolution: {integrity: sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==} dev: true - /shelljs@0.8.5: - resolution: {integrity: sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==} - engines: {node: '>=4'} - hasBin: true - dependencies: - glob: 7.2.3 - interpret: 1.4.0 - rechoir: 0.6.2 - dev: false - /shimmer@1.2.1: resolution: {integrity: sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==} dev: false @@ -16143,12 +15691,6 @@ packages: engines: {node: '>=10.0.0'} dev: false - /split2@2.2.0: - resolution: {integrity: sha512-RAb22TG39LhI31MbreBgIuKiIKhVsawfTgEGqKHTK87aG+ul/PB8Sqoi3I7kVdRWiCfrKxK3uo4/YUkpNvhPbw==} - dependencies: - through2: 2.0.5 - dev: false - /split2@4.2.0: resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} engines: {node: '>= 10.x'} @@ -16161,27 +15703,6 @@ packages: resolution: {integrity: sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==} dev: false - /sqlstring@2.3.3: - resolution: {integrity: sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==} - engines: {node: '>= 0.6'} - dev: false - - /sshpk@1.18.0: - resolution: {integrity: sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==} - engines: {node: '>=0.10.0'} - hasBin: true - dependencies: - asn1: 0.2.6 - assert-plus: 1.0.0 - bcrypt-pbkdf: 1.0.2 - dashdash: 1.14.1 - ecc-jsbn: 0.1.2 - getpass: 0.1.7 - jsbn: 0.1.1 - safer-buffer: 2.1.2 - tweetnacl: 0.14.5 - dev: false - /ssri@9.0.1: resolution: {integrity: sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} @@ -16196,10 +15717,6 @@ packages: escape-string-regexp: 2.0.0 dev: true - /standard-as-callback@2.1.0: - resolution: {integrity: sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==} - dev: false - /starkbank-ecdsa@1.1.5: resolution: {integrity: sha512-5O9CJ0QF6pTrtDg6dmaHy1GC/2wA1tcXsYanWOCzg+2cZrCDylEvEl6krzI4Zy8ryar00lHErRTT2Q61w/MUVA==} dependencies: @@ -16217,11 +15734,6 @@ packages: engines: {node: '>= 0.8'} dev: false - /stealthy-require@1.1.1: - resolution: {integrity: sha512-ZnWpYnYugiOVEY5GkcuJK1io5V8QmNYChG62gSit9pQVGErXtrKuPC55ITaVSukmMta5qpMU7vqLt2Lnni4f/g==} - engines: {node: '>=0.10.0'} - dev: false - /stream-events@1.0.5: resolution: {integrity: sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==} dependencies: @@ -16331,13 +15843,6 @@ packages: ansi-regex: 3.0.1 dev: false - /strip-ansi@5.2.0: - resolution: {integrity: sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==} - engines: {node: '>=6'} - dependencies: - ansi-regex: 4.1.1 - dev: false - /strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} @@ -16365,12 +15870,6 @@ packages: engines: {node: '>=8'} dev: true - /strip-dirs@2.1.0: - resolution: {integrity: sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==} - dependencies: - is-natural-number: 4.0.1 - dev: false - /strip-eof@1.0.0: resolution: {integrity: sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==} engines: {node: '>=0.10.0'} @@ -16398,7 +15897,7 @@ packages: resolution: {integrity: sha512-JHV2KoL+nMQRXu3m9ervCZZvi4DDCJfzHUE6CmtJxR9TmizyYfrVuhGvnsZLLnheby9Qrnf4Hq6iOEcejGwnGQ==} engines: {node: ^8.1 || >=10.*} dependencies: - '@types/node': 20.10.1 + '@types/node': 20.10.7 qs: 6.11.2 dev: false @@ -16500,12 +15999,6 @@ packages: tslib: 2.6.2 dev: true - /syntax-error@1.4.0: - resolution: {integrity: sha512-YPPlu67mdnHGTup2A8ff7BC2Pjq0e0Yp/IyTFN03zWO0RcK07uLcbi7C2KpGR2FvWbaB0+bfE27a+sBKebSo7w==} - dependencies: - acorn-node: 1.8.2 - dev: false - /systeminformation@5.21.18: resolution: {integrity: sha512-PEoWd95nI5170rvIk4fagLH0SmzwfGt18w0+ex1Ljb2bSXvDs9PQdLNexMazL5L6Pzd6wxlpoWUAjX+hNRKN7g==} engines: {node: '>=8.0.0'} @@ -16529,19 +16022,6 @@ packages: engines: {node: '>=6'} dev: false - /tar-stream@1.6.2: - resolution: {integrity: sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==} - engines: {node: '>= 0.8.0'} - dependencies: - bl: 1.2.3 - buffer-alloc: 1.2.0 - end-of-stream: 1.4.4 - fs-constants: 1.0.0 - readable-stream: 2.3.8 - to-buffer: 1.1.1 - xtend: 4.0.2 - dev: false - /tar@4.4.19: resolution: {integrity: sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==} engines: {node: '>=4.5'} @@ -16575,28 +16055,12 @@ packages: https-proxy-agent: 5.0.1 node-fetch: 2.7.0 stream-events: 1.0.5 - uuid: 8.3.0 + uuid: 8.3.2 transitivePeerDependencies: - encoding - supports-color dev: false - /temp-dir@2.0.0: - resolution: {integrity: sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==} - engines: {node: '>=8'} - dev: false - - /tempy@1.0.1: - resolution: {integrity: sha512-biM9brNqxSc04Ee71hzFbryD11nX7VPhQQY32AdDmjFvodsRFz/3ufeoTZ6uYkRFfGo188tENcASNs3vTdsM0w==} - engines: {node: '>=10'} - dependencies: - del: 6.1.1 - is-stream: 2.0.1 - temp-dir: 2.0.0 - type-fest: 0.16.0 - unique-string: 2.0.0 - dev: false - /term-size@2.2.1: resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==} engines: {node: '>=8'} @@ -16650,11 +16114,6 @@ packages: /text-table@0.2.0: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} - /textextensions@2.6.0: - resolution: {integrity: sha512-49WtAWS+tcsy93dRt6P0P3AMD2m5PvXRhuEA0kaXos5ZLlujtYmpmFsB+QvWUSxE1ZsstmYXfQ7L40+EcQgpAQ==} - engines: {node: '>=0.8'} - dev: false - /thenify-all@1.6.0: resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} engines: {node: '>=0.8'} @@ -16678,20 +16137,12 @@ packages: long: 2.4.0 dev: false - /throttle-debounce@3.0.1: - resolution: {integrity: sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg==} - engines: {node: '>=10'} - dev: false - /through2@2.0.5: resolution: {integrity: sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==} dependencies: readable-stream: 2.3.8 xtend: 4.0.2 - - /through@2.3.8: - resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} - dev: false + dev: true /timers-ext@0.1.7: resolution: {integrity: sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==} @@ -16722,13 +16173,10 @@ packages: resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} dev: true - /to-buffer@1.1.1: - resolution: {integrity: sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==} - dev: false - /to-fast-properties@2.0.0: resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} engines: {node: '>=4'} + dev: true /to-readable-stream@1.0.0: resolution: {integrity: sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==} @@ -16762,14 +16210,6 @@ packages: nopt: 1.0.10 dev: true - /tough-cookie@2.5.0: - resolution: {integrity: sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==} - engines: {node: '>=0.8'} - dependencies: - psl: 1.9.0 - punycode: 2.3.1 - dev: false - /tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} @@ -16919,6 +16359,37 @@ packages: yn: 3.1.1 dev: false + /ts-node@10.9.1(@types/node@20.10.7)(typescript@5.3.2): + resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} + hasBin: true + peerDependencies: + '@swc/core': '>=1.2.50' + '@swc/wasm': '>=1.2.50' + '@types/node': '*' + typescript: '>=2.7' + peerDependenciesMeta: + '@swc/core': + optional: true + '@swc/wasm': + optional: true + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@tsconfig/node10': 1.0.9 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.4 + '@types/node': 20.10.7 + acorn: 8.11.2 + acorn-walk: 8.3.0 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 5.3.2 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + dev: true + /tsconfig-paths@3.14.2: resolution: {integrity: sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==} dependencies: @@ -16956,26 +16427,15 @@ packages: tslib: 1.14.1 typescript: 5.3.2 - /tunnel-agent@0.6.0: - resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} - dependencies: - safe-buffer: 5.2.1 - dev: false - /tunnel@0.0.6: resolution: {integrity: sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==} engines: {node: '>=0.6.11 <=0.7.0 || >=0.7.3'} - dev: true /tv4@1.3.0: resolution: {integrity: sha512-afizzfpJgvPr+eDkREK4MxJ/+r8nEEHcmitwgnPUqpaP+FpwQyadnxNoSACbgc/b1LsZYtODGoPiFxQrgJgjvw==} engines: {node: '>= 0.8.0'} dev: false - /tweetnacl@0.14.5: - resolution: {integrity: sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==} - dev: false - /tx2@1.0.5: resolution: {integrity: sha512-sJ24w0y03Md/bxzK4FU8J8JveYYUbSs2FViLJ2D/8bytSiyPRbuE3DyL/9UKYXTZlV3yXq0L8GLlhobTnekCVg==} requiresBuild: true @@ -16995,11 +16455,6 @@ packages: engines: {node: '>=4'} dev: true - /type-fest@0.16.0: - resolution: {integrity: sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==} - engines: {node: '>=10'} - dev: false - /type-fest@0.20.2: resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} engines: {node: '>=10'} @@ -17115,13 +16570,6 @@ packages: which-boxed-primitive: 1.0.2 dev: true - /unbzip2-stream@1.4.3: - resolution: {integrity: sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==} - dependencies: - buffer: 5.7.1 - through: 2.3.8 - dev: false - /undefsafe@2.0.5: resolution: {integrity: sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==} dev: true @@ -17141,11 +16589,11 @@ packages: engines: {node: '>=14.0'} dependencies: '@fastify/busboy': 2.1.0 - dev: true /unicode-canonical-property-names-ecmascript@2.0.0: resolution: {integrity: sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==} engines: {node: '>=4'} + dev: true /unicode-match-property-ecmascript@2.0.0: resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==} @@ -17153,14 +16601,17 @@ packages: dependencies: unicode-canonical-property-names-ecmascript: 2.0.0 unicode-property-aliases-ecmascript: 2.1.0 + dev: true /unicode-match-property-value-ecmascript@2.1.0: resolution: {integrity: sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==} engines: {node: '>=4'} + dev: true /unicode-property-aliases-ecmascript@2.1.0: resolution: {integrity: sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==} engines: {node: '>=4'} + dev: true /unionfs@4.5.1: resolution: {integrity: sha512-hn8pzkh0/80mpsIT/YBJKa4+BF/9pNh0IgysBi0CjL95Uok8Hus69TNfgeJckoUNwfTpBq26+F7edO1oBINaIw==} @@ -17204,11 +16655,6 @@ packages: engines: {node: '>= 4.0.0'} dev: false - /universalify@2.0.1: - resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} - engines: {node: '>= 10.0.0'} - dev: false - /unleash-client@3.21.0: resolution: {integrity: sha512-I7eYhRyOia3oBZ9Tu1v+IlNO+XJgsjcMEO2+j+e4A7LTTKZvGoV8WPfDGGxiMPKBPHNUACkERB3YhCQ9jzTGoQ==} engines: {node: '>=10', npm: '>=4.0.0'} @@ -17332,11 +16778,6 @@ packages: hasBin: true dev: false - /uuid@8.3.0: - resolution: {integrity: sha512-fX6Z5o4m6XsXBdli9g7DtWgAx+osMsRRZFKma1mIUsLCz6vRvv+pz5VNbyu9UEDzpMWulZfvpgb/cmDXVulYFQ==} - hasBin: true - dev: false - /uuid@8.3.2: resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} hasBin: true @@ -17379,15 +16820,6 @@ packages: resolution: {integrity: sha512-c5Kv/wzbPBii5s2FyZssgarhMCaHCQAXexqKl2JX/BbCCbZ8oRICS+x9E82pdCNnV9az2sd9SOb+MUtdPNHyvA==} dev: false - /verror@1.10.0: - resolution: {integrity: sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==} - engines: {'0': node >=0.6.0} - dependencies: - assert-plus: 1.0.0 - core-util-is: 1.0.2 - extsprintf: 1.3.0 - dev: false - /vizion@2.2.1: resolution: {integrity: sha512-sfAcO2yeSU0CSPFI/DmZp3FsFE9T+8913nv1xWBOyzODv13fwkn6Vl7HqxGpkr9F608M+8SuFId3s+BlZqfXww==} engines: {node: '>=4.0'} @@ -17537,7 +16969,7 @@ packages: /wkx@0.5.0: resolution: {integrity: sha512-Xng/d4Ichh8uN4l0FToV/258EjMGU9MGcA0HV2d9B/ZpZB3lqQm7nkOdZdm5GhKtLLhAE7PiVQwN4eN+2YJJUg==} dependencies: - '@types/node': 20.10.1 + '@types/node': 20.10.7 dev: false /wordwrapjs@4.0.1: @@ -17813,13 +17245,6 @@ packages: yargs-parser: 7.0.0 dev: false - /yauzl@2.10.0: - resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} - dependencies: - buffer-crc32: 0.2.13 - fd-slicer: 1.1.0 - dev: false - /yn@3.1.1: resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} engines: {node: '>=6'} @@ -17891,8 +17316,11 @@ packages: name: '@crowd/archetype-worker' dependencies: '@crowd/archetype-standard': file:services/archetypes/standard(@swc/core@1.3.100)(@types/node@20.10.1)(typescript@5.3.2) + '@crowd/common': file:services/libs/common '@crowd/database': file:services/libs/database + '@crowd/sqs': file:services/libs/sqs '@crowd/temporal': file:services/libs/temporal + '@opensearch-project/opensearch': 1.2.0 '@temporalio/client': 1.8.6 '@temporalio/worker': 1.8.6 '@temporalio/workflow': 1.8.6 @@ -17904,6 +17332,7 @@ packages: - '@swc/helpers' - '@swc/wasm' - '@types/node' + - aws-crt - bluebird - debug - encoding @@ -17919,7 +17348,7 @@ packages: resolution: {directory: services/libs/alerting, type: directory} name: '@crowd/alerting' dependencies: - '@types/node': 20.10.1 + '@types/node': 20.10.7 '@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.54.0)(typescript@5.3.2) '@typescript-eslint/parser': 5.62.0(eslint@8.54.0)(typescript@5.3.2) axios: 1.6.2 @@ -17943,6 +17372,27 @@ packages: psl: 1.9.0 uuid: 9.0.1 transitivePeerDependencies: + - debug + - supports-color + dev: false + + file:services/libs/common_services: + resolution: {directory: services/libs/common_services, type: directory} + name: '@crowd/common_services' + dependencies: + '@crowd/common': file:services/libs/common + '@crowd/database': file:services/libs/database + '@crowd/feature-flags': file:services/libs/feature-flags + '@crowd/logging': file:services/libs/logging + '@crowd/redis': file:services/libs/redis + '@crowd/sqs': file:services/libs/sqs + '@crowd/tracing': file:services/libs/tracing + '@crowd/types': file:services/libs/types + transitivePeerDependencies: + - aws-crt + - bluebird + - debug + - pg-native - supports-color dev: false @@ -17956,26 +17406,24 @@ packages: '@crowd/types': file:services/libs/types html-to-text: 9.0.5 transitivePeerDependencies: + - debug - pg-native - supports-color dev: false - file:services/libs/cubejs(bufferutil@4.0.8)(utf-8-validate@5.0.10): + file:services/libs/cubejs: resolution: {directory: services/libs/cubejs, type: directory} - id: file:services/libs/cubejs name: '@crowd/cubejs' dependencies: '@crowd/common': file:services/libs/common '@crowd/logging': file:services/libs/logging - '@cubejs-backend/server-core': 0.32.31(bufferutil@4.0.8)(utf-8-validate@5.0.10) '@cubejs-client/core': 0.34.27 jsonwebtoken: 9.0.2 moment: 2.29.4 transitivePeerDependencies: - - bufferutil + - debug - encoding - supports-color - - utf-8-validate dev: false file:services/libs/database: @@ -17986,6 +17434,7 @@ packages: '@crowd/logging': file:services/libs/logging pg-promise: 11.5.4 transitivePeerDependencies: + - debug - pg-native - supports-color dev: false @@ -18001,6 +17450,7 @@ packages: unleash-client: 3.21.0 transitivePeerDependencies: - bluebird + - debug - supports-color dev: false @@ -18035,6 +17485,7 @@ packages: bunyan: 1.8.15 bunyan-format: 0.2.1 transitivePeerDependencies: + - debug - supports-color dev: false @@ -18063,6 +17514,7 @@ packages: '@crowd/types': file:services/libs/types redis: 4.6.11 transitivePeerDependencies: + - debug - supports-color dev: false @@ -18075,6 +17527,7 @@ packages: '@crowd/logging': file:services/libs/logging transitivePeerDependencies: - aws-crt + - debug - supports-color dev: false @@ -18091,6 +17544,7 @@ packages: '@smithy/util-retry': 2.0.7 transitivePeerDependencies: - aws-crt + - debug - supports-color dev: false @@ -18101,6 +17555,7 @@ packages: '@crowd/logging': file:services/libs/logging dd-trace: 4.20.0 transitivePeerDependencies: + - debug - supports-color dev: false @@ -18113,6 +17568,7 @@ packages: '@temporalio/common': 1.8.6 '@temporalio/proto': 1.8.6 transitivePeerDependencies: + - debug - supports-color dev: false @@ -18136,12 +17592,17 @@ packages: opentelemetry-instrumentation-kafkajs: 0.39.1(@opentelemetry/api@1.6.0) opentelemetry-instrumentation-sequelize: 0.39.1(@opentelemetry/api@1.6.0) transitivePeerDependencies: + - debug - supports-color dev: false file:services/libs/types: resolution: {directory: services/libs/types, type: directory} name: '@crowd/types' + dependencies: + peopledatalabs: 6.1.5 + transitivePeerDependencies: + - debug dev: false github.com/clearbit/needle/84d28b5f2c3916db1e7eb84aeaa9d976cc40054b: diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index b46d3f46f5..cae9a61ef0 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -2,4 +2,6 @@ packages: - 'services/libs/*' - 'services/archetypes/*' - 'services/apps/*' + - 'services/apps/premium/*' - 'backend' + - '.github/actions/node' diff --git a/scripts/builders/automations-worker.sh b/scripts/builders/automations-worker.env similarity index 52% rename from scripts/builders/automations-worker.sh rename to scripts/builders/automations-worker.env index 639e9f94a9..c58bab3e3f 100644 --- a/scripts/builders/automations-worker.sh +++ b/scripts/builders/automations-worker.env @@ -1,5 +1,4 @@ -#!/usr/bin/env bash - DOCKERFILE="./services/docker/Dockerfile.automations_worker" CONTEXT="../" -REPO="crowddotdev/automations-worker" \ No newline at end of file +REPO="crowddotdev/automations-worker" +SERVICES="automations-worker" \ No newline at end of file diff --git a/scripts/builders/backend.env b/scripts/builders/backend.env new file mode 100644 index 0000000000..63d279bf93 --- /dev/null +++ b/scripts/builders/backend.env @@ -0,0 +1,5 @@ +DOCKERFILE="./services/docker/Dockerfile.backend" +CONTEXT="../" +REPO="crowddotdev/backend" +SERVICES="api job-generator discord-ws nodejs-worker" +PRIORITIZED="nodejs-worker" \ No newline at end of file diff --git a/scripts/builders/backend.sh b/scripts/builders/backend.sh deleted file mode 100644 index 17f275f0c1..0000000000 --- a/scripts/builders/backend.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash - -DOCKERFILE="./services/docker/Dockerfile.backend" -CONTEXT="../" -REPO="crowddotdev/backend" \ No newline at end of file diff --git a/scripts/builders/cache-worker.env b/scripts/builders/cache-worker.env new file mode 100644 index 0000000000..a8386f9d20 --- /dev/null +++ b/scripts/builders/cache-worker.env @@ -0,0 +1,4 @@ +DOCKERFILE="./services/docker/Dockerfile.cache_worker" +CONTEXT="../" +REPO="crowddotdev/cache-worker" +SERVICES="cache-worker" \ No newline at end of file diff --git a/scripts/builders/cubejs.sh b/scripts/builders/cubejs.env similarity index 84% rename from scripts/builders/cubejs.sh rename to scripts/builders/cubejs.env index f126391419..e9e76ab8e9 100644 --- a/scripts/builders/cubejs.sh +++ b/scripts/builders/cubejs.env @@ -1,5 +1,3 @@ -#!/usr/bin/env bash - DOCKERFILE="../services/libs/cubejs/Dockerfile" CONTEXT="../services/libs/cubejs/src" REPO="crowddotdev/cubejs" \ No newline at end of file diff --git a/scripts/builders/data-sink-worker.env b/scripts/builders/data-sink-worker.env new file mode 100644 index 0000000000..6d9561dcd8 --- /dev/null +++ b/scripts/builders/data-sink-worker.env @@ -0,0 +1,5 @@ +DOCKERFILE="./services/docker/Dockerfile.data_sink_worker" +CONTEXT="../" +REPO="crowddotdev/data-sink-worker" +SERVICES="data-sink-worker" +PRIORITIZED="data-sink-worker" \ No newline at end of file diff --git a/scripts/builders/data-sink-worker.sh b/scripts/builders/data-sink-worker.sh deleted file mode 100644 index f3b66358ea..0000000000 --- a/scripts/builders/data-sink-worker.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash - -DOCKERFILE="./services/docker/Dockerfile.data_sink_worker" -CONTEXT="../" -REPO="crowddotdev/data-sink-worker" \ No newline at end of file diff --git a/scripts/builders/db.sh b/scripts/builders/db.env similarity index 79% rename from scripts/builders/db.sh rename to scripts/builders/db.env index 99c5be1174..85446bb2a4 100644 --- a/scripts/builders/db.sh +++ b/scripts/builders/db.env @@ -1,5 +1,3 @@ -#!/usr/bin/env bash - DOCKERFILE="./scaffold/db/Dockerfile" CONTEXT="./scaffold/db" REPO="crowddotdev/db" \ No newline at end of file diff --git a/scripts/builders/elasticmq.sh b/scripts/builders/elasticmq.env similarity index 80% rename from scripts/builders/elasticmq.sh rename to scripts/builders/elasticmq.env index ee8520eb00..7f838da910 100644 --- a/scripts/builders/elasticmq.sh +++ b/scripts/builders/elasticmq.env @@ -1,5 +1,3 @@ -#!/usr/bin/env bash - DOCKERFILE="scaffold/sqs/Dockerfile" CONTEXT="scaffold/sqs" REPO="crowddotdev/elasticmq" \ No newline at end of file diff --git a/scripts/builders/emails-worker.sh b/scripts/builders/emails-worker.env similarity index 55% rename from scripts/builders/emails-worker.sh rename to scripts/builders/emails-worker.env index b8782a01ae..c9c5583269 100644 --- a/scripts/builders/emails-worker.sh +++ b/scripts/builders/emails-worker.env @@ -1,5 +1,4 @@ -#!/usr/bin/env bash - DOCKERFILE="./services/docker/Dockerfile.emails_worker" CONTEXT="../" -REPO="crowddotdev/emails-worker" \ No newline at end of file +REPO="crowddotdev/emails-worker" +SERVICES="emails-worker" \ No newline at end of file diff --git a/scripts/builders/entity-merging-worker.env b/scripts/builders/entity-merging-worker.env new file mode 100644 index 0000000000..a722cec743 --- /dev/null +++ b/scripts/builders/entity-merging-worker.env @@ -0,0 +1,4 @@ +DOCKERFILE="./services/docker/Dockerfile.entity_merging_worker" +CONTEXT="../" +REPO="crowddotdev/entity-merging-worker" +SERVICES="entity-merging-worker" \ No newline at end of file diff --git a/scripts/builders/frontend-dev.sh b/scripts/builders/frontend-dev.env similarity index 52% rename from scripts/builders/frontend-dev.sh rename to scripts/builders/frontend-dev.env index 9448a6565e..950bb09fb0 100644 --- a/scripts/builders/frontend-dev.sh +++ b/scripts/builders/frontend-dev.env @@ -1,5 +1,4 @@ -#!/usr/bin/env bash - DOCKERFILE="../frontend/Dockerfile.dev" CONTEXT="../frontend" -REPO="crowddotdev/frontend-dev" \ No newline at end of file +REPO="crowddotdev/frontend-dev" +SERVICES="frontend-dev" \ No newline at end of file diff --git a/scripts/builders/frontend.sh b/scripts/builders/frontend.env similarity index 56% rename from scripts/builders/frontend.sh rename to scripts/builders/frontend.env index e9c7ff90f6..c781c35984 100644 --- a/scripts/builders/frontend.sh +++ b/scripts/builders/frontend.env @@ -1,5 +1,4 @@ -#!/usr/bin/env bash - DOCKERFILE="../frontend/Dockerfile.kube" CONTEXT="../frontend" -REPO="crowddotdev/frontend" \ No newline at end of file +REPO="crowddotdev/frontend" +SERVICES="frontend" \ No newline at end of file diff --git a/scripts/builders/integration-data-worker.env b/scripts/builders/integration-data-worker.env new file mode 100644 index 0000000000..63fb7da8b2 --- /dev/null +++ b/scripts/builders/integration-data-worker.env @@ -0,0 +1,5 @@ +DOCKERFILE="./services/docker/Dockerfile.integration_data_worker" +CONTEXT="../" +REPO="crowddotdev/integration-data-worker" +SERVICES="integration-data-worker" +PRIORITIZED="integration-data-worker" \ No newline at end of file diff --git a/scripts/builders/integration-data-worker.sh b/scripts/builders/integration-data-worker.sh deleted file mode 100644 index 551b856cbd..0000000000 --- a/scripts/builders/integration-data-worker.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash - -DOCKERFILE="./services/docker/Dockerfile.integration_data_worker" -CONTEXT="../" -REPO="crowddotdev/integration-data-worker" \ No newline at end of file diff --git a/scripts/builders/integration-run-worker.env b/scripts/builders/integration-run-worker.env new file mode 100644 index 0000000000..7f8eea89a6 --- /dev/null +++ b/scripts/builders/integration-run-worker.env @@ -0,0 +1,5 @@ +DOCKERFILE="./services/docker/Dockerfile.integration_run_worker" +CONTEXT="../" +REPO="crowddotdev/integration-run-worker" +SERVICES="integration-run-worker" +PRIORITIZED="integration-run-worker" \ No newline at end of file diff --git a/scripts/builders/integration-run-worker.sh b/scripts/builders/integration-run-worker.sh deleted file mode 100644 index 31a6208749..0000000000 --- a/scripts/builders/integration-run-worker.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash - -DOCKERFILE="./services/docker/Dockerfile.integration_run_worker" -CONTEXT="../" -REPO="crowddotdev/integration-run-worker" \ No newline at end of file diff --git a/scripts/builders/integration-stream-worker.env b/scripts/builders/integration-stream-worker.env new file mode 100644 index 0000000000..92b7fac56e --- /dev/null +++ b/scripts/builders/integration-stream-worker.env @@ -0,0 +1,5 @@ +DOCKERFILE="./services/docker/Dockerfile.integration_stream_worker" +CONTEXT="../" +REPO="crowddotdev/integration-stream-worker" +SERVICES="integration-stream-worker" +PRIORITIZED="integration-stream-worker" \ No newline at end of file diff --git a/scripts/builders/integration-stream-worker.sh b/scripts/builders/integration-stream-worker.sh deleted file mode 100644 index d5ec786b58..0000000000 --- a/scripts/builders/integration-stream-worker.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash - -DOCKERFILE="./services/docker/Dockerfile.integration_stream_worker" -CONTEXT="../" -REPO="crowddotdev/integration-stream-worker" \ No newline at end of file diff --git a/scripts/builders/integration-sync-worker.env b/scripts/builders/integration-sync-worker.env new file mode 100644 index 0000000000..be41c3d293 --- /dev/null +++ b/scripts/builders/integration-sync-worker.env @@ -0,0 +1,5 @@ +DOCKERFILE="./services/docker/Dockerfile.integration_sync_worker" +CONTEXT="../" +REPO="crowddotdev/integration-sync-worker" +SERVICES="integration-sync-worker" +PRIORITIZED="integration-sync-worker" \ No newline at end of file diff --git a/scripts/builders/integration-sync-worker.sh b/scripts/builders/integration-sync-worker.sh deleted file mode 100644 index 9e1e288b7c..0000000000 --- a/scripts/builders/integration-sync-worker.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash - -DOCKERFILE="./services/docker/Dockerfile.integration_sync_worker" -CONTEXT="../" -REPO="crowddotdev/integration-sync-worker" \ No newline at end of file diff --git a/scripts/builders/members-enrichment-worker.env b/scripts/builders/members-enrichment-worker.env new file mode 100644 index 0000000000..d2063f1752 --- /dev/null +++ b/scripts/builders/members-enrichment-worker.env @@ -0,0 +1,4 @@ +DOCKERFILE="./services/docker/Dockerfile.members_enrichment_worker" +CONTEXT="../" +REPO="crowddotdev/members-enrichment-worker" +SERVICES="members-enrichment-worker" diff --git a/scripts/builders/merge-suggestions-worker.env b/scripts/builders/merge-suggestions-worker.env new file mode 100644 index 0000000000..49fbb9ac59 --- /dev/null +++ b/scripts/builders/merge-suggestions-worker.env @@ -0,0 +1,4 @@ +DOCKERFILE="./services/docker/Dockerfile.merge_suggestions_worker" +CONTEXT="../" +REPO="crowddotdev/merge-suggestions-worker" +SERVICES="merge-suggestions-worker" \ No newline at end of file diff --git a/scripts/builders/nginx.sh b/scripts/builders/nginx.env similarity index 80% rename from scripts/builders/nginx.sh rename to scripts/builders/nginx.env index 1e00c1b019..b68a93ce29 100644 --- a/scripts/builders/nginx.sh +++ b/scripts/builders/nginx.env @@ -1,5 +1,3 @@ -#!/usr/bin/env bash - DOCKERFILE="scaffold/nginx/Dockerfile" CONTEXT="scaffold/nginx" REPO="crowddotdev/nginx" \ No newline at end of file diff --git a/scripts/builders/organizations-enrichment-worker.env b/scripts/builders/organizations-enrichment-worker.env new file mode 100644 index 0000000000..c37fd6427f --- /dev/null +++ b/scripts/builders/organizations-enrichment-worker.env @@ -0,0 +1,4 @@ +DOCKERFILE="./services/docker/Dockerfile.organizations_enrichment_worker" +CONTEXT="../" +REPO="crowddotdev/organizations-enrichment-worker" +SERVICES="organizations-enrichment-worker" \ No newline at end of file diff --git a/scripts/builders/profiles-worker.env b/scripts/builders/profiles-worker.env new file mode 100644 index 0000000000..494b591013 --- /dev/null +++ b/scripts/builders/profiles-worker.env @@ -0,0 +1,4 @@ +DOCKERFILE="./services/docker/Dockerfile.profiles_worker" +CONTEXT="../" +REPO="crowddotdev/profiles-worker" +SERVICES="profiles-worker" \ No newline at end of file diff --git a/scripts/builders/python-worker.sh b/scripts/builders/python-worker.env similarity index 70% rename from scripts/builders/python-worker.sh rename to scripts/builders/python-worker.env index f24fd5c8f0..afa2ba4ca7 100644 --- a/scripts/builders/python-worker.sh +++ b/scripts/builders/python-worker.env @@ -1,5 +1,4 @@ -#!/usr/bin/env bash - DOCKERFILE="../backend/src/serverless/microservices/python/Dockerfile.kube" CONTEXT="../backend/src/serverless/microservices/python" -REPO="crowddotdev/python-worker" \ No newline at end of file +REPO="crowddotdev/python-worker" +SERVICES="python-worker" \ No newline at end of file diff --git a/scripts/builders/redis.sh b/scripts/builders/redis.env similarity index 80% rename from scripts/builders/redis.sh rename to scripts/builders/redis.env index c83ce74973..271cb76b02 100644 --- a/scripts/builders/redis.sh +++ b/scripts/builders/redis.env @@ -1,5 +1,3 @@ -#!/usr/bin/env bash - DOCKERFILE="scaffold/redis/Dockerfile" CONTEXT="scaffold/redis" REPO="crowddotdev/redis" \ No newline at end of file diff --git a/scripts/builders/script-executor.sh b/scripts/builders/script-executor.env similarity index 54% rename from scripts/builders/script-executor.sh rename to scripts/builders/script-executor.env index 68c3e7e59a..d24cec27aa 100644 --- a/scripts/builders/script-executor.sh +++ b/scripts/builders/script-executor.env @@ -1,5 +1,4 @@ -#!/usr/bin/env bash - DOCKERFILE="./services/docker/Dockerfile.script_executor" CONTEXT="../" -REPO="crowddotdev/script-executor" \ No newline at end of file +REPO="crowddotdev/script-executor" +SERVICES="script-executor" \ No newline at end of file diff --git a/scripts/builders/search-sync-api.sh b/scripts/builders/search-sync-api.env similarity index 54% rename from scripts/builders/search-sync-api.sh rename to scripts/builders/search-sync-api.env index 7144cf0f13..bbb22c1725 100644 --- a/scripts/builders/search-sync-api.sh +++ b/scripts/builders/search-sync-api.env @@ -1,5 +1,4 @@ -#!/usr/bin/env bash - DOCKERFILE="./services/docker/Dockerfile.search_sync_api" CONTEXT="../" -REPO="crowddotdev/search-sync-api" \ No newline at end of file +REPO="crowddotdev/search-sync-api" +SERVICES="search-sync-api" \ No newline at end of file diff --git a/scripts/builders/search-sync-worker.env b/scripts/builders/search-sync-worker.env new file mode 100644 index 0000000000..628dccb886 --- /dev/null +++ b/scripts/builders/search-sync-worker.env @@ -0,0 +1,5 @@ +DOCKERFILE="./services/docker/Dockerfile.search_sync_worker" +CONTEXT="../" +REPO="crowddotdev/search-sync-worker" +SERVICES="search-sync-worker" +PRIORITIZED="search-sync-worker" \ No newline at end of file diff --git a/scripts/builders/search-sync-worker.sh b/scripts/builders/search-sync-worker.sh deleted file mode 100644 index 53412bb795..0000000000 --- a/scripts/builders/search-sync-worker.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash - -DOCKERFILE="./services/docker/Dockerfile.search_sync_worker" -CONTEXT="../" -REPO="crowddotdev/search-sync-worker" \ No newline at end of file diff --git a/scripts/builders/webhook-api.sh b/scripts/builders/webhook-api.env similarity index 56% rename from scripts/builders/webhook-api.sh rename to scripts/builders/webhook-api.env index ed212fd6b4..2228094006 100644 --- a/scripts/builders/webhook-api.sh +++ b/scripts/builders/webhook-api.env @@ -1,5 +1,4 @@ -#!/usr/bin/env bash - DOCKERFILE="./services/docker/Dockerfile.webhook_api" CONTEXT="../" -REPO="crowddotdev/webhook-api" \ No newline at end of file +REPO="crowddotdev/webhook-api" +SERVICES="webhook-api" \ No newline at end of file diff --git a/scripts/cli b/scripts/cli index 69ae29fb68..33b86ddb1c 100755 --- a/scripts/cli +++ b/scripts/cli @@ -105,10 +105,12 @@ function build_and_publish() { VERSION="$TS_VERSION.$COMMIT_HASH" fi - source $CLI_HOME/builders/$1.sh + source $CLI_HOME/builders/$1.env - say "Building $REPO version $VERSION with dockerfile '$DOCKERFILE' and context '$CONTEXT' and pushing it to $REPO:$VERSION" - docker build --platform linux/amd64 --tag "$REPO:$VERSION" -f "$DOCKERFILE" "$CONTEXT" + if [[ ${BUILD} ]]; then + say "Building $REPO version $VERSION with dockerfile '$DOCKERFILE' and context '$CONTEXT' and pushing it to $REPO:$VERSION" + docker build --platform linux/amd64 --tag "$REPO:$VERSION" -f "$DOCKERFILE" "$CONTEXT" + fi if [[ ${PUSH} ]]; then say "Pushing image $REPO version $VERSION to $REPO:$VERSION" @@ -524,6 +526,13 @@ do start exit; ;; + clean-start-backend) + declare -a INGORED_SERVICES=("frontend") + CLEAN_START=1 + DEV=1 + start + exit; + ;; start-backend) declare -a INGORED_SERVICES=("frontend") start @@ -586,10 +595,17 @@ do exit; ;; build) + BUILD=1 build $2 $3 exit; ;; build-and-push) + BUILD=1 + PUSH=1 + build $2 $3 + exit; + ;; + push) PUSH=1 build $2 $3 exit; diff --git a/scripts/scaffold.yaml b/scripts/scaffold.yaml index bb1c29877b..6761c2194c 100644 --- a/scripts/scaffold.yaml +++ b/scripts/scaffold.yaml @@ -3,7 +3,7 @@ version: '3.1' services: cubejs: build: - context: ../services/libs/cubejs + context: ../services/libs/cubejs/src/app restart: always ports: - '4000:4000' @@ -44,6 +44,7 @@ services: - bootstrap.memory_lock=true - 'DISABLE_INSTALL_DEMO_CONFIG=true' - 'DISABLE_SECURITY_PLUGIN=true' + - cluster.routing.allocation.disk.threshold_enabled=false ulimits: memlock: soft: -1 @@ -134,20 +135,20 @@ services: networks: - crowd-bridge - kafka: - image: bitnami/kafka:latest - restart: always - environment: - - KAFKA_CFG_NODE_ID=0 - - KAFKA_CFG_PROCESS_ROLES=controller,broker - - KAFKA_CFG_LISTENERS=PLAINTEXT://:9092,CONTROLLER://:9093 - - KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT - - KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=0@kafka:9093 - - KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER - ports: - - '9092:9092' - networks: - - crowd-bridge + # kafka: + # image: bitnami/kafka:latest + # restart: always + # environment: + # - KAFKA_CFG_NODE_ID=0 + # - KAFKA_CFG_PROCESS_ROLES=controller,broker + # - KAFKA_CFG_LISTENERS=PLAINTEXT://:9092,CONTROLLER://:9093 + # - KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT + # - KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=0@kafka:9093 + # - KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER + # ports: + # - '9092:9092' + # networks: + # - crowd-bridge temporal: build: diff --git a/scripts/scaffold/sqs/queue.conf b/scripts/scaffold/sqs/queue.conf index 6610fcbe94..fae65a7ed8 100644 --- a/scripts/scaffold/sqs/queue.conf +++ b/scripts/scaffold/sqs/queue.conf @@ -5,19 +5,6 @@ node-address { } queues { - "nodejs-worker.fifo" { - fifo = true - contentBasedDeduplication = false - receiveMessageWait = 30 seconds - delay = 0 seconds - defaultVisibilityTimeout = 0 seconds - } - "nodejs-worker" { - contentBasedDeduplication = false - receiveMessageWait = 30 seconds - delay = 0 seconds - defaultVisibilityTimeout = 0 seconds - } "python-worker.fifo" { fifo = true contentBasedDeduplication = false @@ -25,41 +12,6 @@ queues { delay = 0 seconds defaultVisibilityTimeout = 0 seconds } - "premium-python-worker.fifo" { - fifo = true - contentBasedDeduplication = false - receiveMessageWait = 30 seconds - delay = 0 seconds - defaultVisibilityTimeout = 0 seconds - } - "integration-run-worker.fifo" { - fifo = true - contentBasedDeduplication = false - receiveMessageWait = 30 seconds - delay = 0 seconds - defaultVisibilityTimeout = 0 seconds - } - "integration-data-worker.fifo" { - fifo = true - contentBasedDeduplication = false - receiveMessageWait = 30 seconds - delay = 0 seconds - defaultVisibilityTimeout = 0 seconds - } - "integration-stream-worker.fifo" { - fifo = true - contentBasedDeduplication = false - receiveMessageWait = 30 seconds - delay = 0 seconds - defaultVisibilityTimeout = 0 seconds - } - "data-sink-worker.fifo" { - fifo = true - contentBasedDeduplication = false - receiveMessageWait = 30 seconds - delay = 0 seconds - defaultVisibilityTimeout = 0 seconds - } } aws { diff --git a/scripts/scaffold/temporal/Dockerfile b/scripts/scaffold/temporal/Dockerfile index c37f6b7186..d982fe64a2 100755 --- a/scripts/scaffold/temporal/Dockerfile +++ b/scripts/scaffold/temporal/Dockerfile @@ -1,10 +1,12 @@ FROM alpine:latest -RUN apk add curl +RUN apk cache clean && apk add --no-cache curl RUN curl -sSf https://temporal.download/cli.sh | sh ENV PATH /root/.temporalio/bin:$PATH EXPOSE 7233 8233 -ENTRYPOINT ["temporal", "server", "start-dev", "--ip", "0.0.0.0"] +COPY ./entrypoint.sh /entrypoint.sh + +ENTRYPOINT [ "/entrypoint.sh" ] diff --git a/scripts/scaffold/temporal/entrypoint.sh b/scripts/scaffold/temporal/entrypoint.sh new file mode 100755 index 0000000000..9891759210 --- /dev/null +++ b/scripts/scaffold/temporal/entrypoint.sh @@ -0,0 +1,27 @@ +#!/bin/sh + +temporal server start-dev --ip 0.0.0.0 & + +# Function to check if Temporal is ready +check_temporal_ready() { + # Execute the Temporal health check command + temporal operator cluster health + + # Return the exit status of the health check command + return $? +} + +# Wait for Temporal server to be ready +echo "Waiting for Temporal server to be ready..." +until check_temporal_ready; do + printf '.' + sleep 1 +done +echo "Temporal server is ready." + +# Run Temporal setup command +temporal operator search-attribute create --name TenantId --type Text --namespace default + +# Keep the container running after setup +# (This could be tailing logs or just a sleep loop) +tail -f /dev/null diff --git a/scripts/services/api.yaml b/scripts/services/api.yaml index 85851fb30d..9c85811fd6 100644 --- a/scripts/services/api.yaml +++ b/scripts/services/api.yaml @@ -48,6 +48,7 @@ services: volumes: - ../../services/libs/alerting/src:/usr/crowd/app/services/libs/alerting/src - ../../services/libs/common/src:/usr/crowd/app/services/libs/common/src + - ../../services/libs/common_services/src:/usr/crowd/app/services/libs/common_services/src - ../../services/libs/conversations/src:/usr/crowd/app/services/libs/conversations/src - ../../services/libs/database/src:/usr/crowd/app/services/libs/database/src - ../../services/libs/integrations/src:/usr/crowd/app/services/libs/integrations/src diff --git a/scripts/services/automations-worker.yaml b/scripts/services/automations-worker.yaml index e3bd0a0634..4e028392b8 100644 --- a/scripts/services/automations-worker.yaml +++ b/scripts/services/automations-worker.yaml @@ -45,6 +45,7 @@ services: volumes: - ../../services/libs/alerting/src:/usr/crowd/app/services/libs/alerting/src - ../../services/libs/common/src:/usr/crowd/app/services/libs/common/src + - ../../services/libs/common_services/src:/usr/crowd/app/services/libs/common_services/src - ../../services/libs/conversations/src:/usr/crowd/app/services/libs/conversations/src - ../../services/libs/database/src:/usr/crowd/app/services/libs/database/src - ../../services/libs/integrations/src:/usr/crowd/app/services/libs/integrations/src diff --git a/scripts/services/cache-worker.yaml b/scripts/services/cache-worker.yaml new file mode 100644 index 0000000000..d8b29fb6dd --- /dev/null +++ b/scripts/services/cache-worker.yaml @@ -0,0 +1,63 @@ +version: '3.1' + +x-env-args: &env-args + DOCKER_BUILDKIT: 1 + NODE_ENV: docker + SERVICE: cache-worker + CROWD_TEMPORAL_TASKQUEUE: cache + SHELL: /bin/sh + +services: + cache-worker: + build: + context: ../../ + dockerfile: ./scripts/services/docker/Dockerfile.cache_worker + command: 'pnpm run start' + working_dir: /usr/crowd/app/services/apps/cache_worker + env_file: + - ../../backend/.env.dist.local + - ../../backend/.env.dist.composed + - ../../backend/.env.override.local + - ../../backend/.env.override.composed + environment: + <<: *env-args + restart: always + networks: + - crowd-bridge + + cache-worker-dev: + build: + context: ../../ + dockerfile: ./scripts/services/docker/Dockerfile.cache_worker + command: 'pnpm run dev' + working_dir: /usr/crowd/app/services/apps/cache_worker + # user: '${USER_ID}:${GROUP_ID}' + env_file: + - ../../backend/.env.dist.local + - ../../backend/.env.dist.composed + - ../../backend/.env.override.local + - ../../backend/.env.override.composed + environment: + <<: *env-args + hostname: cache-worker + networks: + - crowd-bridge + volumes: + - ../../services/libs/alerting/src:/usr/crowd/app/services/libs/alerting/src + - ../../services/libs/common/src:/usr/crowd/app/services/libs/common/src + - ../../services/libs/common_services/src:/usr/crowd/app/services/libs/common_services/src + - ../../services/libs/conversations/src:/usr/crowd/app/services/libs/conversations/src + - ../../services/libs/database/src:/usr/crowd/app/services/libs/database/src + - ../../services/libs/integrations/src:/usr/crowd/app/services/libs/integrations/src + - ../../services/libs/ioc/src:/usr/crowd/app/services/libs/ioc/src + - ../../services/libs/logging/src:/usr/crowd/app/services/libs/logging/src + - ../../services/libs/opensearch/src:/usr/crowd/app/services/libs/opensearch/src + - ../../services/libs/redis/src:/usr/crowd/app/services/libs/redis/src + - ../../services/libs/sentiment/src:/usr/crowd/app/services/libs/sentiment/src + - ../../services/libs/sqs/src:/usr/crowd/app/services/libs/sqs/src + - ../../services/libs/types/src:/usr/crowd/app/services/libs/types/src + - ../../services/apps/cache_worker/src:/usr/crowd/app/services/apps/cache_worker/src + +networks: + crowd-bridge: + external: true diff --git a/scripts/services/data-sink-worker.yaml b/scripts/services/data-sink-worker.yaml index 4e70372f5e..ff8f4087e1 100644 --- a/scripts/services/data-sink-worker.yaml +++ b/scripts/services/data-sink-worker.yaml @@ -5,6 +5,7 @@ x-env-args: &env-args NODE_ENV: docker SERVICE: data-sink-worker SHELL: /bin/sh + QUEUE_PRIORITY_LEVEL: normal services: data-sink-worker: @@ -44,6 +45,7 @@ services: volumes: - ../../services/libs/alerting/src:/usr/crowd/app/services/libs/alerting/src - ../../services/libs/common/src:/usr/crowd/app/services/libs/common/src + - ../../services/libs/common_services/src:/usr/crowd/app/services/libs/common_services/src - ../../services/libs/conversations/src:/usr/crowd/app/services/libs/conversations/src - ../../services/libs/database/src:/usr/crowd/app/services/libs/database/src - ../../services/libs/integrations/src:/usr/crowd/app/services/libs/integrations/src diff --git a/scripts/services/discord-ws.yaml b/scripts/services/discord-ws.yaml index 949e682a14..d75fd5f120 100644 --- a/scripts/services/discord-ws.yaml +++ b/scripts/services/discord-ws.yaml @@ -43,6 +43,7 @@ services: volumes: - ../../services/libs/alerting/src:/usr/crowd/app/services/libs/alerting/src - ../../services/libs/common/src:/usr/crowd/app/services/libs/common/src + - ../../services/libs/common_services/src:/usr/crowd/app/services/libs/common_services/src - ../../services/libs/conversations/src:/usr/crowd/app/services/libs/conversations/src - ../../services/libs/database/src:/usr/crowd/app/services/libs/database/src - ../../services/libs/integrations/src:/usr/crowd/app/services/libs/integrations/src diff --git a/scripts/services/docker/Dockerfile.cache_worker b/scripts/services/docker/Dockerfile.cache_worker new file mode 100644 index 0000000000..ebc2107e71 --- /dev/null +++ b/scripts/services/docker/Dockerfile.cache_worker @@ -0,0 +1,18 @@ +FROM node:16-alpine as builder + +WORKDIR /usr/crowd/app +RUN corepack enable && apk add --update --no-cache python3 build-base && ln -sf python3 /usr/bin/python && python3 -m ensurepip && pip3 install --no-cache --upgrade pip setuptools + +COPY ./pnpm-workspace.yaml ./pnpm-lock.yaml ./ +COPY ./services ./services +RUN pnpm i --frozen-lockfile + +FROM node:16-bookworm-slim as runner + +WORKDIR /usr/crowd/app +RUN corepack enable && apt update && apt install -y ca-certificates --no-install-recommends && rm -rf /var/lib/apt/lists/* + +COPY --from=builder /usr/crowd/app/node_modules ./node_modules +COPY --from=builder /usr/crowd/app/services/libs ./services/libs +COPY --from=builder /usr/crowd/app/services/archetypes/ ./services/archetypes +COPY --from=builder /usr/crowd/app/services/apps/cache_worker/ ./services/apps/cache_worker \ No newline at end of file diff --git a/scripts/services/docker/Dockerfile.cache_worker.dockerignore b/scripts/services/docker/Dockerfile.cache_worker.dockerignore new file mode 100644 index 0000000000..77d313162a --- /dev/null +++ b/scripts/services/docker/Dockerfile.cache_worker.dockerignore @@ -0,0 +1,22 @@ +**/.git +**/node_modules +**/venv* +**/.webpack +**/.serverless +**/.cubestore +**/.env +**/.env.* +**/.idea +**/.vscode +**/dist +backend/server-config/ +backend/util/ +backend/src/serverless/microservices/python +.vscode/ +.github/ +frontend/ +scripts/ +.flake8 +*.md +Makefile +backend/ \ No newline at end of file diff --git a/scripts/services/docker/Dockerfile.entity_merging_worker b/scripts/services/docker/Dockerfile.entity_merging_worker new file mode 100644 index 0000000000..20e53539fd --- /dev/null +++ b/scripts/services/docker/Dockerfile.entity_merging_worker @@ -0,0 +1,18 @@ +FROM node:16-alpine as builder + +WORKDIR /usr/crowd/app +RUN corepack enable && apk add --update --no-cache python3 build-base && ln -sf python3 /usr/bin/python && python3 -m ensurepip && pip3 install --no-cache --upgrade pip setuptools + +COPY ./pnpm-workspace.yaml ./pnpm-lock.yaml ./ +COPY ./services ./services +RUN pnpm i --frozen-lockfile + +FROM node:16-bookworm-slim as runner + +WORKDIR /usr/crowd/app +RUN corepack enable && apt update && apt install -y ca-certificates --no-install-recommends && rm -rf /var/lib/apt/lists/* + +COPY --from=builder /usr/crowd/app/node_modules ./node_modules +COPY --from=builder /usr/crowd/app/services/libs ./services/libs +COPY --from=builder /usr/crowd/app/services/archetypes/ ./services/archetypes +COPY --from=builder /usr/crowd/app/services/apps/entity_merging_worker/ ./services/apps/entity_merging_worker diff --git a/scripts/services/docker/Dockerfile.entity_merging_worker.dockerignore b/scripts/services/docker/Dockerfile.entity_merging_worker.dockerignore new file mode 100644 index 0000000000..59c09254a9 --- /dev/null +++ b/scripts/services/docker/Dockerfile.entity_merging_worker.dockerignore @@ -0,0 +1,22 @@ +**/.git +**/node_modules +**/venv* +**/.webpack +**/.serverless +**/.cubestore +**/.env +**/.env.* +**/.idea +**/.vscode +**/dist +backend/server-config/ +backend/util/ +backend/src/serverless/microservices/python +.vscode/ +.github/ +frontend/ +scripts/ +.flake8 +*.md +Makefile +backend/ diff --git a/scripts/services/docker/Dockerfile.members_enrichment_worker b/scripts/services/docker/Dockerfile.members_enrichment_worker new file mode 100644 index 0000000000..b7eafd5bc5 --- /dev/null +++ b/scripts/services/docker/Dockerfile.members_enrichment_worker @@ -0,0 +1,18 @@ +FROM node:16-alpine as builder + +WORKDIR /usr/crowd/app +RUN corepack enable && apk add --update --no-cache python3 build-base && ln -sf python3 /usr/bin/python && python3 -m ensurepip && pip3 install --no-cache --upgrade pip setuptools + +COPY ./pnpm-workspace.yaml ./pnpm-lock.yaml ./ +COPY ./services ./services +RUN pnpm i --frozen-lockfile + +FROM node:16-bookworm-slim as runner + +WORKDIR /usr/crowd/app +RUN corepack enable && apt update && apt install -y ca-certificates --no-install-recommends && rm -rf /var/lib/apt/lists/* + +COPY --from=builder /usr/crowd/app/node_modules ./node_modules +COPY --from=builder /usr/crowd/app/services/libs ./services/libs +COPY --from=builder /usr/crowd/app/services/archetypes/ ./services/archetypes +COPY --from=builder /usr/crowd/app/services/apps/premium/members_enrichment_worker/ ./services/apps/premium/members_enrichment_worker diff --git a/scripts/services/docker/Dockerfile.members_enrichment_worker.dockerignore b/scripts/services/docker/Dockerfile.members_enrichment_worker.dockerignore new file mode 100644 index 0000000000..77d313162a --- /dev/null +++ b/scripts/services/docker/Dockerfile.members_enrichment_worker.dockerignore @@ -0,0 +1,22 @@ +**/.git +**/node_modules +**/venv* +**/.webpack +**/.serverless +**/.cubestore +**/.env +**/.env.* +**/.idea +**/.vscode +**/dist +backend/server-config/ +backend/util/ +backend/src/serverless/microservices/python +.vscode/ +.github/ +frontend/ +scripts/ +.flake8 +*.md +Makefile +backend/ \ No newline at end of file diff --git a/scripts/services/docker/Dockerfile.merge_suggestions_worker b/scripts/services/docker/Dockerfile.merge_suggestions_worker new file mode 100644 index 0000000000..2bfe3897e9 --- /dev/null +++ b/scripts/services/docker/Dockerfile.merge_suggestions_worker @@ -0,0 +1,18 @@ +FROM node:16-alpine as builder + +WORKDIR /usr/crowd/app +RUN corepack enable && apk add --update --no-cache python3 build-base && ln -sf python3 /usr/bin/python && python3 -m ensurepip && pip3 install --no-cache --upgrade pip setuptools + +COPY ./pnpm-workspace.yaml ./pnpm-lock.yaml ./ +COPY ./services ./services +RUN pnpm i --frozen-lockfile + +FROM node:16-bookworm-slim as runner + +WORKDIR /usr/crowd/app +RUN corepack enable && apt update && apt install -y ca-certificates --no-install-recommends && rm -rf /var/lib/apt/lists/* + +COPY --from=builder /usr/crowd/app/node_modules ./node_modules +COPY --from=builder /usr/crowd/app/services/libs ./services/libs +COPY --from=builder /usr/crowd/app/services/archetypes/ ./services/archetypes +COPY --from=builder /usr/crowd/app/services/apps/merge_suggestions_worker/ ./services/apps/merge_suggestions_worker \ No newline at end of file diff --git a/scripts/services/docker/Dockerfile.merge_suggestions_worker.dockerignore b/scripts/services/docker/Dockerfile.merge_suggestions_worker.dockerignore new file mode 100644 index 0000000000..77d313162a --- /dev/null +++ b/scripts/services/docker/Dockerfile.merge_suggestions_worker.dockerignore @@ -0,0 +1,22 @@ +**/.git +**/node_modules +**/venv* +**/.webpack +**/.serverless +**/.cubestore +**/.env +**/.env.* +**/.idea +**/.vscode +**/dist +backend/server-config/ +backend/util/ +backend/src/serverless/microservices/python +.vscode/ +.github/ +frontend/ +scripts/ +.flake8 +*.md +Makefile +backend/ \ No newline at end of file diff --git a/scripts/services/docker/Dockerfile.organizations_enrichment_worker b/scripts/services/docker/Dockerfile.organizations_enrichment_worker new file mode 100644 index 0000000000..f84b767090 --- /dev/null +++ b/scripts/services/docker/Dockerfile.organizations_enrichment_worker @@ -0,0 +1,18 @@ +FROM node:16-alpine as builder + +WORKDIR /usr/crowd/app +RUN corepack enable && apk add --update --no-cache python3 build-base && ln -sf python3 /usr/bin/python && python3 -m ensurepip && pip3 install --no-cache --upgrade pip setuptools + +COPY ./pnpm-workspace.yaml ./pnpm-lock.yaml ./ +COPY ./services ./services +RUN pnpm i --frozen-lockfile + +FROM node:16-bookworm-slim as runner + +WORKDIR /usr/crowd/app +RUN corepack enable && apt update && apt install -y ca-certificates --no-install-recommends && rm -rf /var/lib/apt/lists/* + +COPY --from=builder /usr/crowd/app/node_modules ./node_modules +COPY --from=builder /usr/crowd/app/services/libs ./services/libs +COPY --from=builder /usr/crowd/app/services/archetypes/ ./services/archetypes +COPY --from=builder /usr/crowd/app/services/apps/premium/organizations_enrichment_worker/ ./services/apps/premium/organizations_enrichment_worker diff --git a/scripts/services/docker/Dockerfile.organizations_enrichment_worker.dockerignore b/scripts/services/docker/Dockerfile.organizations_enrichment_worker.dockerignore new file mode 100644 index 0000000000..77d313162a --- /dev/null +++ b/scripts/services/docker/Dockerfile.organizations_enrichment_worker.dockerignore @@ -0,0 +1,22 @@ +**/.git +**/node_modules +**/venv* +**/.webpack +**/.serverless +**/.cubestore +**/.env +**/.env.* +**/.idea +**/.vscode +**/dist +backend/server-config/ +backend/util/ +backend/src/serverless/microservices/python +.vscode/ +.github/ +frontend/ +scripts/ +.flake8 +*.md +Makefile +backend/ \ No newline at end of file diff --git a/scripts/services/docker/Dockerfile.profiles_worker b/scripts/services/docker/Dockerfile.profiles_worker new file mode 100644 index 0000000000..ddcf8631f4 --- /dev/null +++ b/scripts/services/docker/Dockerfile.profiles_worker @@ -0,0 +1,18 @@ +FROM node:16-alpine as builder + +WORKDIR /usr/crowd/app +RUN corepack enable && apk add --update --no-cache python3 build-base && ln -sf python3 /usr/bin/python && python3 -m ensurepip && pip3 install --no-cache --upgrade pip setuptools + +COPY ./pnpm-workspace.yaml ./pnpm-lock.yaml ./ +COPY ./services ./services +RUN pnpm i --frozen-lockfile + +FROM node:16-bookworm-slim as runner + +WORKDIR /usr/crowd/app +RUN corepack enable && apt update && apt install -y ca-certificates --no-install-recommends && rm -rf /var/lib/apt/lists/* + +COPY --from=builder /usr/crowd/app/node_modules ./node_modules +COPY --from=builder /usr/crowd/app/services/libs ./services/libs +COPY --from=builder /usr/crowd/app/services/archetypes/ ./services/archetypes +COPY --from=builder /usr/crowd/app/services/apps/profiles_worker/ ./services/apps/profiles_worker diff --git a/scripts/services/emails-worker.yaml b/scripts/services/emails-worker.yaml index 5cc1b38f96..7fd559b435 100644 --- a/scripts/services/emails-worker.yaml +++ b/scripts/services/emails-worker.yaml @@ -45,6 +45,7 @@ services: volumes: - ../../services/libs/alerting/src:/usr/crowd/app/services/libs/alerting/src - ../../services/libs/common/src:/usr/crowd/app/services/libs/common/src + - ../../services/libs/common_services/src:/usr/crowd/app/services/libs/common_services/src - ../../services/libs/conversations/src:/usr/crowd/app/services/libs/conversations/src - ../../services/libs/cubejs/src:/usr/crowd/app/services/libs/cubejs/src - ../../services/libs/database/src:/usr/crowd/app/services/libs/database/src diff --git a/scripts/services/entity-merging-worker.yaml b/scripts/services/entity-merging-worker.yaml new file mode 100644 index 0000000000..cda9b6f95a --- /dev/null +++ b/scripts/services/entity-merging-worker.yaml @@ -0,0 +1,63 @@ +version: '3.1' + +x-env-args: &env-args + DOCKER_BUILDKIT: 1 + NODE_ENV: docker + SERVICE: entity-merging-worker + CROWD_TEMPORAL_TASKQUEUE: entity-merging + SHELL: /bin/sh + +services: + entity-merging-worker: + build: + context: ../../ + dockerfile: ./scripts/services/docker/Dockerfile.entity_merging_worker + command: 'pnpm run start' + working_dir: /usr/crowd/app/services/apps/entity_merging_worker + env_file: + - ../../backend/.env.dist.local + - ../../backend/.env.dist.composed + - ../../backend/.env.override.local + - ../../backend/.env.override.composed + environment: + <<: *env-args + restart: always + networks: + - crowd-bridge + + entity-merging-worker-dev: + build: + context: ../../ + dockerfile: ./scripts/services/docker/Dockerfile.entity_merging_worker + command: 'pnpm run dev' + working_dir: /usr/crowd/app/services/apps/entity_merging_worker + # user: '${USER_ID}:${GROUP_ID}' + env_file: + - ../../backend/.env.dist.local + - ../../backend/.env.dist.composed + - ../../backend/.env.override.local + - ../../backend/.env.override.composed + environment: + <<: *env-args + hostname: entity-merging-worker + networks: + - crowd-bridge + volumes: + - ../../services/libs/alerting/src:/usr/crowd/app/services/libs/alerting/src + - ../../services/libs/common/src:/usr/crowd/app/services/libs/common/src + - ../../services/libs/conversations/src:/usr/crowd/app/services/libs/conversations/src + - ../../services/libs/cubejs/src:/usr/crowd/app/services/libs/cubejs/src + - ../../services/libs/database/src:/usr/crowd/app/services/libs/database/src + - ../../services/libs/integrations/src:/usr/crowd/app/services/libs/integrations/src + - ../../services/libs/ioc/src:/usr/crowd/app/services/libs/ioc/src + - ../../services/libs/logging/src:/usr/crowd/app/services/libs/logging/src + - ../../services/libs/opensearch/src:/usr/crowd/app/services/libs/opensearch/src + - ../../services/libs/redis/src:/usr/crowd/app/services/libs/redis/src + - ../../services/libs/sentiment/src:/usr/crowd/app/services/libs/sentiment/src + - ../../services/libs/sqs/src:/usr/crowd/app/services/libs/sqs/src + - ../../services/libs/types/src:/usr/crowd/app/services/libs/types/src + - ../../services/apps/entity_merging_worker/src:/usr/crowd/app/services/apps/entity_merging_worker/src + +networks: + crowd-bridge: + external: true diff --git a/scripts/services/integration-data-worker.yaml b/scripts/services/integration-data-worker.yaml index e3651d949b..5a46b23a71 100644 --- a/scripts/services/integration-data-worker.yaml +++ b/scripts/services/integration-data-worker.yaml @@ -5,6 +5,7 @@ x-env-args: &env-args NODE_ENV: docker SERVICE: integration-data-worker SHELL: /bin/sh + QUEUE_PRIORITY_LEVEL: normal services: integration-data-worker: @@ -44,6 +45,7 @@ services: volumes: - ../../services/libs/alerting/src:/usr/crowd/app/services/libs/alerting/src - ../../services/libs/common/src:/usr/crowd/app/services/libs/common/src + - ../../services/libs/common_services/src:/usr/crowd/app/services/libs/common_services/src - ../../services/libs/conversations/src:/usr/crowd/app/services/libs/conversations/src - ../../services/libs/database/src:/usr/crowd/app/services/libs/database/src - ../../services/libs/integrations/src:/usr/crowd/app/services/libs/integrations/src diff --git a/scripts/services/integration-run-worker.yaml b/scripts/services/integration-run-worker.yaml index e89fb8dafc..6302db487b 100644 --- a/scripts/services/integration-run-worker.yaml +++ b/scripts/services/integration-run-worker.yaml @@ -5,6 +5,7 @@ x-env-args: &env-args NODE_ENV: docker SERVICE: integration-run-worker SHELL: /bin/sh + QUEUE_PRIORITY_LEVEL: normal services: integration-run-worker: @@ -44,6 +45,7 @@ services: volumes: - ../../services/libs/alerting/src:/usr/crowd/app/services/libs/alerting/src - ../../services/libs/common/src:/usr/crowd/app/services/libs/common/src + - ../../services/libs/common_services/src:/usr/crowd/app/services/libs/common_services/src - ../../services/libs/conversations/src:/usr/crowd/app/services/libs/conversations/src - ../../services/libs/database/src:/usr/crowd/app/services/libs/database/src - ../../services/libs/integrations/src:/usr/crowd/app/services/libs/integrations/src diff --git a/scripts/services/integration-stream-worker.yaml b/scripts/services/integration-stream-worker.yaml index f997093998..72992469a1 100644 --- a/scripts/services/integration-stream-worker.yaml +++ b/scripts/services/integration-stream-worker.yaml @@ -5,6 +5,7 @@ x-env-args: &env-args NODE_ENV: docker SERVICE: integration-stream-worker SHELL: /bin/sh + QUEUE_PRIORITY_LEVEL: normal services: integration-stream-worker: @@ -44,6 +45,7 @@ services: volumes: - ../../services/libs/alerting/src:/usr/crowd/app/services/libs/alerting/src - ../../services/libs/common/src:/usr/crowd/app/services/libs/common/src + - ../../services/libs/common_services/src:/usr/crowd/app/services/libs/common_services/src - ../../services/libs/conversations/src:/usr/crowd/app/services/libs/conversations/src - ../../services/libs/database/src:/usr/crowd/app/services/libs/database/src - ../../services/libs/integrations/src:/usr/crowd/app/services/libs/integrations/src diff --git a/scripts/services/integration-sync-worker.yaml b/scripts/services/integration-sync-worker.yaml index 745d3ef52f..06057202ce 100644 --- a/scripts/services/integration-sync-worker.yaml +++ b/scripts/services/integration-sync-worker.yaml @@ -5,6 +5,7 @@ x-env-args: &env-args NODE_ENV: docker SERVICE: integration-sync-worker SHELL: /bin/sh + QUEUE_PRIORITY_LEVEL: normal services: integration-sync-worker: @@ -44,6 +45,7 @@ services: volumes: - ../../services/libs/alerting/src:/usr/crowd/app/services/libs/alerting/src - ../../services/libs/common/src:/usr/crowd/app/services/libs/common/src + - ../../services/libs/common_services/src:/usr/crowd/app/services/libs/common_services/src - ../../services/libs/conversations/src:/usr/crowd/app/services/libs/conversations/src - ../../services/libs/database/src:/usr/crowd/app/services/libs/database/src - ../../services/libs/integrations/src:/usr/crowd/app/services/libs/integrations/src diff --git a/scripts/services/job-generator.yaml b/scripts/services/job-generator.yaml index fedaaa33ab..b87aba81cc 100644 --- a/scripts/services/job-generator.yaml +++ b/scripts/services/job-generator.yaml @@ -44,6 +44,7 @@ services: volumes: - ../../services/libs/alerting/src:/usr/crowd/app/services/libs/alerting/src - ../../services/libs/common/src:/usr/crowd/app/services/libs/common/src + - ../../services/libs/common_services/src:/usr/crowd/app/services/libs/common_services/src - ../../services/libs/conversations/src:/usr/crowd/app/services/libs/conversations/src - ../../services/libs/database/src:/usr/crowd/app/services/libs/database/src - ../../services/libs/integrations/src:/usr/crowd/app/services/libs/integrations/src diff --git a/scripts/services/members-enrichment-worker.yaml b/scripts/services/members-enrichment-worker.yaml new file mode 100644 index 0000000000..48afabe77b --- /dev/null +++ b/scripts/services/members-enrichment-worker.yaml @@ -0,0 +1,63 @@ +version: '3.1' + +x-env-args: &env-args + DOCKER_BUILDKIT: 1 + NODE_ENV: docker + SERVICE: members-enrichment-worker + CROWD_TEMPORAL_TASKQUEUE: members-enrichment + SHELL: /bin/sh + +services: + members-enrichment-worker: + build: + context: ../../ + dockerfile: ./scripts/services/docker/Dockerfile.members_enrichment_worker + command: 'pnpm run start' + working_dir: /usr/crowd/app/services/apps/members_enrichment_worker + env_file: + - ../../backend/.env.dist.local + - ../../backend/.env.dist.composed + - ../../backend/.env.override.local + - ../../backend/.env.override.composed + environment: + <<: *env-args + restart: always + networks: + - crowd-bridge + + members-enrichment-worker-dev: + build: + context: ../../ + dockerfile: ./scripts/services/docker/Dockerfile.members_enrichment_worker + command: 'pnpm run dev' + working_dir: /usr/crowd/app/services/apps/premium/members_enrichment_worker + # user: '${USER_ID}:${GROUP_ID}' + env_file: + - ../../backend/.env.dist.local + - ../../backend/.env.dist.composed + - ../../backend/.env.override.local + - ../../backend/.env.override.composed + environment: + <<: *env-args + hostname: members-enrichment-worker + networks: + - crowd-bridge + volumes: + - ../../services/libs/alerting/src:/usr/crowd/app/services/libs/alerting/src + - ../../services/libs/common/src:/usr/crowd/app/services/libs/common/src + - ../../services/libs/common_services/src:/usr/crowd/app/services/libs/common_services/src + - ../../services/libs/conversations/src:/usr/crowd/app/services/libs/conversations/src + - ../../services/libs/database/src:/usr/crowd/app/services/libs/database/src + - ../../services/libs/integrations/src:/usr/crowd/app/services/libs/integrations/src + - ../../services/libs/ioc/src:/usr/crowd/app/services/libs/ioc/src + - ../../services/libs/logging/src:/usr/crowd/app/services/libs/logging/src + - ../../services/libs/opensearch/src:/usr/crowd/app/services/libs/opensearch/src + - ../../services/libs/redis/src:/usr/crowd/app/services/libs/redis/src + - ../../services/libs/sentiment/src:/usr/crowd/app/services/libs/sentiment/src + - ../../services/libs/sqs/src:/usr/crowd/app/services/libs/sqs/src + - ../../services/libs/types/src:/usr/crowd/app/services/libs/types/src + - ../../services/apps/premium/members_enrichment_worker/src:/usr/crowd/app/services/apps/premium/members_enrichment_worker/src + +networks: + crowd-bridge: + external: true diff --git a/scripts/services/merge-suggestions-worker.yaml b/scripts/services/merge-suggestions-worker.yaml new file mode 100644 index 0000000000..d9373f7e00 --- /dev/null +++ b/scripts/services/merge-suggestions-worker.yaml @@ -0,0 +1,63 @@ +version: '3.1' + +x-env-args: &env-args + DOCKER_BUILDKIT: 1 + NODE_ENV: docker + SERVICE: merge-suggestions-worker + CROWD_TEMPORAL_TASKQUEUE: merge-suggestions + SHELL: /bin/sh + +services: + merge-suggestions-worker: + build: + context: ../../ + dockerfile: ./scripts/services/docker/Dockerfile.merge_suggestions_worker + command: 'pnpm run start' + working_dir: /usr/crowd/app/services/apps/merge_suggestions_worker + env_file: + - ../../backend/.env.dist.local + - ../../backend/.env.dist.composed + - ../../backend/.env.override.local + - ../../backend/.env.override.composed + environment: + <<: *env-args + restart: always + networks: + - crowd-bridge + + merge-suggestions-worker-dev: + build: + context: ../../ + dockerfile: ./scripts/services/docker/Dockerfile.merge_suggestions_worker + command: 'pnpm run dev' + working_dir: /usr/crowd/app/services/apps/merge_suggestions_worker + # user: '${USER_ID}:${GROUP_ID}' + env_file: + - ../../backend/.env.dist.local + - ../../backend/.env.dist.composed + - ../../backend/.env.override.local + - ../../backend/.env.override.composed + environment: + <<: *env-args + hostname: merge-suggestions-worker + networks: + - crowd-bridge + volumes: + - ../../services/libs/alerting/src:/usr/crowd/app/services/libs/alerting/src + - ../../services/libs/common/src:/usr/crowd/app/services/libs/common/src + - ../../services/libs/common_services/src:/usr/crowd/app/services/libs/common_services/src + - ../../services/libs/conversations/src:/usr/crowd/app/services/libs/conversations/src + - ../../services/libs/database/src:/usr/crowd/app/services/libs/database/src + - ../../services/libs/integrations/src:/usr/crowd/app/services/libs/integrations/src + - ../../services/libs/ioc/src:/usr/crowd/app/services/libs/ioc/src + - ../../services/libs/logging/src:/usr/crowd/app/services/libs/logging/src + - ../../services/libs/opensearch/src:/usr/crowd/app/services/libs/opensearch/src + - ../../services/libs/redis/src:/usr/crowd/app/services/libs/redis/src + - ../../services/libs/sentiment/src:/usr/crowd/app/services/libs/sentiment/src + - ../../services/libs/sqs/src:/usr/crowd/app/services/libs/sqs/src + - ../../services/libs/types/src:/usr/crowd/app/services/libs/types/src + - ../../services/apps/merge_suggestions_worker/src:/usr/crowd/app/services/apps/merge_suggestions_worker/src + +networks: + crowd-bridge: + external: true diff --git a/scripts/services/nodejs-worker.yaml b/scripts/services/nodejs-worker.yaml index d5a9e18804..c35f7aec2f 100644 --- a/scripts/services/nodejs-worker.yaml +++ b/scripts/services/nodejs-worker.yaml @@ -5,6 +5,7 @@ x-env-args: &env-args NODE_ENV: docker SERVICE: nodejs-worker SHELL: /bin/sh + QUEUE_PRIORITY_LEVEL: normal services: nodejs-worker: @@ -44,6 +45,7 @@ services: volumes: - ../../services/libs/alerting/src:/usr/crowd/app/services/libs/alerting/src - ../../services/libs/common/src:/usr/crowd/app/services/libs/common/src + - ../../services/libs/common_services/src:/usr/crowd/app/services/libs/common_services/src - ../../services/libs/conversations/src:/usr/crowd/app/services/libs/conversations/src - ../../services/libs/database/src:/usr/crowd/app/services/libs/database/src - ../../services/libs/integrations/src:/usr/crowd/app/services/libs/integrations/src diff --git a/scripts/services/organizations-enrichment-worker.yaml b/scripts/services/organizations-enrichment-worker.yaml new file mode 100644 index 0000000000..2852807b35 --- /dev/null +++ b/scripts/services/organizations-enrichment-worker.yaml @@ -0,0 +1,63 @@ +version: '3.1' + +x-env-args: &env-args + DOCKER_BUILDKIT: 1 + NODE_ENV: docker + SERVICE: organizations-enrichment-worker + CROWD_TEMPORAL_TASKQUEUE: organizations-enrichment + SHELL: /bin/sh + +services: + organizations-enrichment-worker: + build: + context: ../../ + dockerfile: ./scripts/services/docker/Dockerfile.organizations_enrichment_worker + command: 'pnpm run start' + working_dir: /usr/crowd/app/services/apps/organizations_enrichment_worker + env_file: + - ../../backend/.env.dist.local + - ../../backend/.env.dist.composed + - ../../backend/.env.override.local + - ../../backend/.env.override.composed + environment: + <<: *env-args + restart: always + networks: + - crowd-bridge + + organizations-enrichment-worker-dev: + build: + context: ../../ + dockerfile: ./scripts/services/docker/Dockerfile.organizations_enrichment_worker + command: 'pnpm run dev' + working_dir: /usr/crowd/app/services/apps/premium/organizations_enrichment_worker + # user: '${USER_ID}:${GROUP_ID}' + env_file: + - ../../backend/.env.dist.local + - ../../backend/.env.dist.composed + - ../../backend/.env.override.local + - ../../backend/.env.override.composed + environment: + <<: *env-args + hostname: organizations-enrichment-worker + networks: + - crowd-bridge + volumes: + - ../../services/libs/alerting/src:/usr/crowd/app/services/libs/alerting/src + - ../../services/libs/common/src:/usr/crowd/app/services/libs/common/src + - ../../services/libs/common_services/src:/usr/crowd/app/services/libs/common_services/src + - ../../services/libs/conversations/src:/usr/crowd/app/services/libs/conversations/src + - ../../services/libs/database/src:/usr/crowd/app/services/libs/database/src + - ../../services/libs/integrations/src:/usr/crowd/app/services/libs/integrations/src + - ../../services/libs/ioc/src:/usr/crowd/app/services/libs/ioc/src + - ../../services/libs/logging/src:/usr/crowd/app/services/libs/logging/src + - ../../services/libs/opensearch/src:/usr/crowd/app/services/libs/opensearch/src + - ../../services/libs/redis/src:/usr/crowd/app/services/libs/redis/src + - ../../services/libs/sentiment/src:/usr/crowd/app/services/libs/sentiment/src + - ../../services/libs/sqs/src:/usr/crowd/app/services/libs/sqs/src + - ../../services/libs/types/src:/usr/crowd/app/services/libs/types/src + - ../../services/apps/premium/organizations_enrichment_worker/src:/usr/crowd/app/services/apps/premium/organizations_enrichment_worker/src + +networks: + crowd-bridge: + external: true diff --git a/scripts/services/profiles-worker.yaml b/scripts/services/profiles-worker.yaml new file mode 100644 index 0000000000..8410b1aec5 --- /dev/null +++ b/scripts/services/profiles-worker.yaml @@ -0,0 +1,64 @@ +version: '3.1' + +x-env-args: &env-args + DOCKER_BUILDKIT: 1 + NODE_ENV: docker + SERVICE: profiles-worker + CROWD_TEMPORAL_TASKQUEUE: profiles + SHELL: /bin/sh + +services: + profiles-worker: + build: + context: ../../ + dockerfile: ./scripts/services/docker/Dockerfile.profiles_worker + command: 'pnpm run start' + working_dir: /usr/crowd/app/services/apps/profiles_worker + env_file: + - ../../backend/.env.dist.local + - ../../backend/.env.dist.composed + - ../../backend/.env.override.local + - ../../backend/.env.override.composed + environment: + <<: *env-args + restart: always + networks: + - crowd-bridge + + profiles-worker-dev: + build: + context: ../../ + dockerfile: ./scripts/services/docker/Dockerfile.profiles_worker + command: 'pnpm run dev' + working_dir: /usr/crowd/app/services/apps/profiles_worker + # user: '${USER_ID}:${GROUP_ID}' + env_file: + - ../../backend/.env.dist.local + - ../../backend/.env.dist.composed + - ../../backend/.env.override.local + - ../../backend/.env.override.composed + environment: + <<: *env-args + hostname: profiles-worker + networks: + - crowd-bridge + volumes: + - ../../services/libs/alerting/src:/usr/crowd/app/services/libs/alerting/src + - ../../services/libs/common/src:/usr/crowd/app/services/libs/common/src + - ../../services/libs/common_services/src:/usr/crowd/app/services/libs/common_services/src + - ../../services/libs/conversations/src:/usr/crowd/app/services/libs/conversations/src + - ../../services/libs/cubejs/src:/usr/crowd/app/services/libs/cubejs/src + - ../../services/libs/database/src:/usr/crowd/app/services/libs/database/src + - ../../services/libs/integrations/src:/usr/crowd/app/services/libs/integrations/src + - ../../services/libs/ioc/src:/usr/crowd/app/services/libs/ioc/src + - ../../services/libs/logging/src:/usr/crowd/app/services/libs/logging/src + - ../../services/libs/opensearch/src:/usr/crowd/app/services/libs/opensearch/src + - ../../services/libs/redis/src:/usr/crowd/app/services/libs/redis/src + - ../../services/libs/sentiment/src:/usr/crowd/app/services/libs/sentiment/src + - ../../services/libs/sqs/src:/usr/crowd/app/services/libs/sqs/src + - ../../services/libs/types/src:/usr/crowd/app/services/libs/types/src + - ../../services/apps/profiles_worker/src:/usr/crowd/app/services/apps/profiles_worker/src + +networks: + crowd-bridge: + external: true diff --git a/scripts/services/search-sync-api.yaml b/scripts/services/search-sync-api.yaml index e059f4bee8..f8a371a88f 100644 --- a/scripts/services/search-sync-api.yaml +++ b/scripts/services/search-sync-api.yaml @@ -48,6 +48,7 @@ services: volumes: - ../../services/libs/alerting/src:/usr/crowd/app/services/libs/alerting/src - ../../services/libs/common/src:/usr/crowd/app/services/libs/common/src + - ../../services/libs/common_services/src:/usr/crowd/app/services/libs/common_services/src - ../../services/libs/conversations/src:/usr/crowd/app/services/libs/conversations/src - ../../services/libs/database/src:/usr/crowd/app/services/libs/database/src - ../../services/libs/integrations/src:/usr/crowd/app/services/libs/integrations/src diff --git a/scripts/services/search-sync-worker.yaml b/scripts/services/search-sync-worker.yaml index f32d4b5d7b..9c9293bb05 100644 --- a/scripts/services/search-sync-worker.yaml +++ b/scripts/services/search-sync-worker.yaml @@ -5,6 +5,7 @@ x-env-args: &env-args NODE_ENV: docker SERVICE: search-sync-worker SHELL: /bin/sh + QUEUE_PRIORITY_LEVEL: normal services: search-sync-worker: @@ -44,6 +45,7 @@ services: volumes: - ../../services/libs/alerting/src:/usr/crowd/app/services/libs/alerting/src - ../../services/libs/common/src:/usr/crowd/app/services/libs/common/src + - ../../services/libs/common_services/src:/usr/crowd/app/services/libs/common_services/src - ../../services/libs/conversations/src:/usr/crowd/app/services/libs/conversations/src - ../../services/libs/database/src:/usr/crowd/app/services/libs/database/src - ../../services/libs/integrations/src:/usr/crowd/app/services/libs/integrations/src diff --git a/scripts/services/webhook-api.yaml b/scripts/services/webhook-api.yaml index 592c044765..7777aac4bb 100644 --- a/scripts/services/webhook-api.yaml +++ b/scripts/services/webhook-api.yaml @@ -48,6 +48,7 @@ services: volumes: - ../../services/libs/alerting/src:/usr/crowd/app/services/libs/alerting/src - ../../services/libs/common/src:/usr/crowd/app/services/libs/common/src + - ../../services/libs/common_services/src:/usr/crowd/app/services/libs/common_services/src - ../../services/libs/conversations/src:/usr/crowd/app/services/libs/conversations/src - ../../services/libs/database/src:/usr/crowd/app/services/libs/database/src - ../../services/libs/integrations/src:/usr/crowd/app/services/libs/integrations/src diff --git a/services/apps/automations_worker/src/main.ts b/services/apps/automations_worker/src/main.ts index e5802a5a26..8df4828544 100644 --- a/services/apps/automations_worker/src/main.ts +++ b/services/apps/automations_worker/src/main.ts @@ -18,6 +18,9 @@ const options: Options = { postgres: { enabled: true, }, + opensearch: { + enabled: false, + }, } export const svc = new ServiceWorker(config, options) diff --git a/services/apps/cache_worker/.eslintrc.cjs b/services/apps/cache_worker/.eslintrc.cjs new file mode 100644 index 0000000000..25ba4e0d66 --- /dev/null +++ b/services/apps/cache_worker/.eslintrc.cjs @@ -0,0 +1,21 @@ +module.exports = { + parser: '@typescript-eslint/parser', + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:prettier/recommended', + ], + plugins: ['@typescript-eslint', 'prettier'], + parserOptions: { + ecmaVersion: 2022, + sourceType: 'module', + }, + env: { + es6: true, + node: true, + }, + rules: { + 'prettier/prettier': 'error', + '@typescript-eslint/explicit-module-boundary-types': 'off', + }, +} diff --git a/services/apps/cache_worker/.prettierignore b/services/apps/cache_worker/.prettierignore new file mode 100644 index 0000000000..2b24877309 --- /dev/null +++ b/services/apps/cache_worker/.prettierignore @@ -0,0 +1,3 @@ +dist/ +.eslintrc.cjs +.prettierrc.cjs diff --git a/services/apps/cache_worker/.prettierrc.cjs b/services/apps/cache_worker/.prettierrc.cjs new file mode 100644 index 0000000000..a8ca459839 --- /dev/null +++ b/services/apps/cache_worker/.prettierrc.cjs @@ -0,0 +1,7 @@ +module.exports = { + singleQuote: true, + arrowParens: 'always', + printWidth: 100, + trailingComma: 'all', + semi: false, +} diff --git a/services/apps/cache_worker/package.json b/services/apps/cache_worker/package.json new file mode 100644 index 0000000000..48bddbc2d2 --- /dev/null +++ b/services/apps/cache_worker/package.json @@ -0,0 +1,44 @@ +{ + "name": "@crowd/cache-worker", + "version": "1.0.0", + "private": true, + "scripts": { + "start": "CROWD_TEMPORAL_TASKQUEUE=cache SERVICE=cache-worker TS_NODE_TRANSPILE_ONLY=true node -r tsconfig-paths/register -r ts-node/register src/main.ts", + "start:debug:local": "set -a && . ../../../backend/.env.dist.local && . ../../../backend/.env.override.local && set +a && CROWD_TEMPORAL_TASKQUEUE=cache SERVICE=cache-worker TS_NODE_TRANSPILE_ONLY=true LOG_LEVEL=trace node --inspect=0.0.0.0:9232 -r tsconfig-paths/register -r ts-node/register src/main.ts", + "start:debug": "CROWD_TEMPORAL_TASKQUEUE=cache SERVICE=cache-worker TS_NODE_TRANSPILE_ONLY=true LOG_LEVEL=trace node --inspect=0.0.0.0:9232 -r tsconfig-paths/register -r ts-node/register src/main.ts", + "dev:local": "./node_modules/.bin/nodemon --watch src --watch ../../libs --ext ts --exec pnpm run start:debug:local", + "dev": "./node_modules/.bin/nodemon --watch src --watch ../../libs --ext ts --exec pnpm run start:debug", + "lint": "./node_modules/.bin/eslint --ext .ts src --max-warnings=0", + "format": "./node_modules/.bin/prettier --write \"src/**/*.ts\"", + "format-check": "./node_modules/.bin/prettier --check .", + "tsc-check": "./node_modules/.bin/tsc --noEmit" + }, + "dependencies": { + "@crowd/archetype-standard": "file:../../archetypes/standard", + "@crowd/archetype-worker": "file:../../archetypes/worker", + "@crowd/common": "file:../../libs/common", + "@crowd/cubejs": "file:../../libs/cubejs", + "@crowd/types": "file:../../libs/types", + "@crowd/feature-flags": "file:../../libs/feature-flags", + "@temporalio/activity": "~1.8.6", + "@temporalio/client": "~1.8.6", + "@temporalio/workflow": "~1.8.6", + "axios": "~1.5.1", + "moment": "~2.29.4", + "ts-node": "^10.9.1", + "tsconfig-paths": "^4.2.0", + "typescript": "^5.2.2", + "uuid": "~9.0.1" + }, + "devDependencies": { + "@types/node": "^20.8.2", + "@types/uuid": "~9.0.6", + "@typescript-eslint/eslint-plugin": "^6.7.4", + "@typescript-eslint/parser": "^6.7.4", + "eslint": "^8.50.0", + "eslint-config-prettier": "^9.0.0", + "eslint-plugin-prettier": "^5.0.0", + "nodemon": "^3.0.1", + "prettier": "^3.0.3" + } +} diff --git a/services/apps/cache_worker/src/activities.ts b/services/apps/cache_worker/src/activities.ts new file mode 100644 index 0000000000..94bc23db0e --- /dev/null +++ b/services/apps/cache_worker/src/activities.ts @@ -0,0 +1,40 @@ +import { + getAllTenants, + getAllSegments, + getProjectLeafSegments, + getProjectGroupLeafSegments, + isSegmentsEnabled, +} from './activities/getTenantSegmentInfo' + +import { + getDashboardCacheLastRefreshedAt, + getDefaultSegment, + getNewMembers, + getActiveMembers, + getNewOrganizations, + getActiveOrganizations, + getActivities, + saveToCache, + getActivePlatforms, + findNewActivityPlatforms, + updateMemberMergeSuggestionsLastGeneratedAt, +} from './activities/dashboard-cache/refreshDashboardCache' + +export { + getAllTenants, + getAllSegments, + getProjectLeafSegments, + getProjectGroupLeafSegments, + getDashboardCacheLastRefreshedAt, + getDefaultSegment, + getNewMembers, + getActiveMembers, + getNewOrganizations, + getActiveOrganizations, + getActivities, + saveToCache, + getActivePlatforms, + findNewActivityPlatforms, + updateMemberMergeSuggestionsLastGeneratedAt, + isSegmentsEnabled, +} diff --git a/services/apps/cache_worker/src/activities/dashboard-cache/refreshDashboardCache.ts b/services/apps/cache_worker/src/activities/dashboard-cache/refreshDashboardCache.ts new file mode 100644 index 0000000000..d998ae30ec --- /dev/null +++ b/services/apps/cache_worker/src/activities/dashboard-cache/refreshDashboardCache.ts @@ -0,0 +1,175 @@ +import { svc } from '../../main' +import { ICubeQueryParams, IDashboardData, ISegment } from 'types' +import SegmentRepository from 'repo/segment.repo' +import { CubeJsRepository, CubeJsService } from '@crowd/cubejs' +import { RedisCache } from '@crowd/redis' +import { DashboardTimeframe } from '@crowd/types' +import moment from 'moment' +import IntegrationRepository from 'repo/integration.repo' +import ActivityRepository from 'repo/activity.repo' + +export async function getDashboardCacheLastRefreshedAt(segmentId: string): Promise { + const segmentRepo = new SegmentRepository(svc.postgres.writer.connection(), svc.log) + return segmentRepo.getDashboardCacheLastRefreshedAt(segmentId) +} + +export async function getDefaultSegment(tenantId: string): Promise { + const segmentRepo = new SegmentRepository(svc.postgres.writer.connection(), svc.log) + return segmentRepo.getDefaultSegment(tenantId) +} + +export async function getActivePlatforms(leafSegmentIds: string[]): Promise { + const integrationRepo = new IntegrationRepository(svc.postgres.writer.connection(), svc.log) + return integrationRepo.findActivePlatforms(leafSegmentIds) +} + +export async function findNewActivityPlatforms( + dashboardLastRefreshedAt: string, + leafSegmentIds: string[], +): Promise { + const activityRepo = new ActivityRepository(svc.postgres.writer.connection(), svc.log) + return activityRepo.findNewActivityPlatforms(dashboardLastRefreshedAt, leafSegmentIds) +} + +export async function updateMemberMergeSuggestionsLastGeneratedAt( + segmentId: string, +): Promise { + const segmentRepo = new SegmentRepository(svc.postgres.writer.connection(), svc.log) + await segmentRepo.updateDashboardCacheLastRefreshedAt(segmentId) +} + +export async function getNewMembers(params: ICubeQueryParams): Promise { + const cjs = new CubeJsService() + await cjs.init(params.tenantId, params.segmentIds) + + let result: T + try { + result = await CubeJsRepository.getNewMembers( + cjs, + moment(params.startDate), + moment(params.endDate), + params.granularity, + { + platform: params.platform, + }, + {}, + params.rawResult, + ) + } catch (err) { + throw new Error(err) + } + + return result +} + +export async function getActiveMembers(params: ICubeQueryParams): Promise { + const cjs = new CubeJsService() + await cjs.init(params.tenantId, params.segmentIds) + + let result: T + try { + result = await CubeJsRepository.getActiveMembers( + cjs, + moment(params.startDate), + moment(params.endDate), + params.granularity, + { + platform: params.platform, + }, + {}, + params.rawResult, + ) + } catch (err) { + throw new Error(err) + } + + return result +} + +export async function getNewOrganizations(params: ICubeQueryParams): Promise { + const cjs = new CubeJsService() + await cjs.init(params.tenantId, params.segmentIds) + + let result: T + try { + result = await CubeJsRepository.getNewOrganizations( + cjs, + moment(params.startDate), + moment(params.endDate), + params.granularity, + { + platform: params.platform, + }, + {}, + params.rawResult, + ) + } catch (err) { + throw new Error(err) + } + + return result +} + +export async function getActiveOrganizations(params: ICubeQueryParams): Promise { + const cjs = new CubeJsService() + await cjs.init(params.tenantId, params.segmentIds) + + let result: T + try { + result = await CubeJsRepository.getActiveOrganizations( + cjs, + moment(params.startDate), + moment(params.endDate), + params.granularity, + { + platform: params.platform, + }, + {}, + params.rawResult, + ) + } catch (err) { + throw new Error(err) + } + + return result +} + +export async function getActivities(params: ICubeQueryParams): Promise { + const cjs = new CubeJsService() + await cjs.init(params.tenantId, params.segmentIds) + + let result: T + try { + result = await CubeJsRepository.getNewActivities( + cjs, + moment(params.startDate), + moment(params.endDate), + params.granularity, + params.dimensions, + { + platform: params.platform, + }, + params.order, + params.rawResult, + ) + } catch (err) { + throw new Error(err) + } + + return result +} + +export async function saveToCache( + tenantId: string, + segmentId: string, + timeframe: DashboardTimeframe, + cacheData: IDashboardData, + platform?: string, +): Promise { + const redisCache = new RedisCache(`dashboard-cache`, svc.redis, svc.log) + let key = `${tenantId}:${segmentId}:${timeframe}` + if (platform) { + key += `:${platform}` + } + await redisCache.set(key, JSON.stringify(cacheData)) +} diff --git a/services/apps/cache_worker/src/activities/getTenantSegmentInfo.ts b/services/apps/cache_worker/src/activities/getTenantSegmentInfo.ts new file mode 100644 index 0000000000..fc48b8422a --- /dev/null +++ b/services/apps/cache_worker/src/activities/getTenantSegmentInfo.ts @@ -0,0 +1,40 @@ +import { ISegment, ITenant } from 'types' +import { svc } from '../main' +import TenantRepository from 'repo/tenant.repo' +import SegmentRepository from 'repo/segment.repo' +import { isFeatureEnabled } from '@crowd/feature-flags' +import { FeatureFlag } from '@crowd/types' + +export async function getAllTenants(): Promise { + const tenantRepository = new TenantRepository(svc.postgres.writer.connection(), svc.log) + return tenantRepository.getAllTenants() +} + +export async function getAllSegments( + tenantId: string, + limit: number, + offset: number, +): Promise { + const segmentRepository = new SegmentRepository(svc.postgres.writer.connection(), svc.log) + return segmentRepository.getAllSegments(tenantId, limit, offset) +} + +export async function getProjectLeafSegments( + parentSlug: string, + tenantId: string, +): Promise { + const segmentRepository = new SegmentRepository(svc.postgres.writer.connection(), svc.log) + return segmentRepository.getProjectLeafSegments(parentSlug, tenantId) +} + +export async function getProjectGroupLeafSegments( + grandparentSlug: string, + tenantId: string, +): Promise { + const segmentRepository = new SegmentRepository(svc.postgres.writer.connection(), svc.log) + return segmentRepository.getProjectGroupLeafSegments(grandparentSlug, tenantId) +} + +export async function isSegmentsEnabled(): Promise { + return isFeatureEnabled(FeatureFlag.SEGMENTS, null) +} diff --git a/services/apps/cache_worker/src/enums.ts b/services/apps/cache_worker/src/enums.ts new file mode 100644 index 0000000000..2ed0d8a23d --- /dev/null +++ b/services/apps/cache_worker/src/enums.ts @@ -0,0 +1,5 @@ +export enum DashboardTimeframe { + LAST_7_DAYS = '7d', + LAST_14_DAYS = '14d', + LAST_30_DAYS = '30d', +} diff --git a/services/apps/cache_worker/src/main.ts b/services/apps/cache_worker/src/main.ts new file mode 100644 index 0000000000..bcd7853575 --- /dev/null +++ b/services/apps/cache_worker/src/main.ts @@ -0,0 +1,39 @@ +import { Config } from '@crowd/archetype-standard' +import { ServiceWorker, Options } from '@crowd/archetype-worker' + +const config: Config = { + envvars: [], + producer: { + enabled: false, + }, + temporal: { + enabled: true, + }, + redis: { + enabled: true, + }, +} + +const options: Options = { + maxTaskQueueActivitiesPerSecond: process.env['CROWD_TEMPORAL_TASKQUEUE_CACHE_MAX_ACTIVITIES'] + ? Number(process.env['CROWD_TEMPORAL_TASKQUEUE_CACHE_MAX_ACTIVITIES']) + : undefined, + maxConcurrentActivityTaskExecutions: process.env[ + 'CROWD_TEMPORAL_TASKQUEUE_CACHE_CONCURRENT_ACTIVITIES' + ] + ? Number(process.env['CROWD_TEMPORAL_TASKQUEUE_CACHE_CONCURRENT_ACTIVITIES']) + : undefined, + postgres: { + enabled: true, + }, + opensearch: { + enabled: false, + }, +} + +export const svc = new ServiceWorker(config, options) + +setImmediate(async () => { + await svc.init() + await svc.start() +}) diff --git a/services/apps/cache_worker/src/repo/activity.repo.ts b/services/apps/cache_worker/src/repo/activity.repo.ts new file mode 100644 index 0000000000..0f2474efec --- /dev/null +++ b/services/apps/cache_worker/src/repo/activity.repo.ts @@ -0,0 +1,40 @@ +import { DbConnection, DbTransaction } from '@crowd/database' +import { Logger } from '@crowd/logging' +import { IPlatforms } from 'types' + +class ActivityRepository { + constructor( + private readonly connection: DbConnection | DbTransaction, + private readonly log: Logger, + ) {} + + async findNewActivityPlatforms( + dashboardLastRefreshedAt: string, + leafSegmentIds: string[], + ): Promise { + let result: IPlatforms + try { + result = await this.connection.oneOrNone( + ` + select + array_agg(distinct a.platform) as platforms + from mv_activities_cube a + where a."segmentId" in ($(leafSegmentIds:csv)) + and a."createdAt" > $(dashboardLastRefreshedAt) + `, + { + leafSegmentIds, + dashboardLastRefreshedAt, + }, + ) + } catch (err) { + this.log.error('Error while getting all tenants', err) + + throw new Error(err) + } + + return result.platforms + } +} + +export default ActivityRepository diff --git a/services/apps/cache_worker/src/repo/integration.repo.ts b/services/apps/cache_worker/src/repo/integration.repo.ts new file mode 100644 index 0000000000..e52c9a1a6a --- /dev/null +++ b/services/apps/cache_worker/src/repo/integration.repo.ts @@ -0,0 +1,37 @@ +import { DbConnection, DbTransaction } from '@crowd/database' +import { Logger } from '@crowd/logging' +import { IPlatforms } from 'types' + +class IntegrationRepository { + constructor( + private readonly connection: DbConnection | DbTransaction, + private readonly log: Logger, + ) {} + + async findActivePlatforms(leafSegmentIds: string[]): Promise { + let result: IPlatforms + try { + result = await this.connection.oneOrNone( + ` + select + array_agg(distinct i.platform) as platforms + from integrations i + where i."segmentId" in ($(leafSegmentIds:csv)) + and i."deletedAt" is null + and i.status in ('done', 'in-progress'); + `, + { + leafSegmentIds, + }, + ) + } catch (err) { + this.log.error('Error while getting all tenants', err) + + throw new Error(err) + } + + return result.platforms || [] + } +} + +export default IntegrationRepository diff --git a/services/apps/cache_worker/src/repo/segment.repo.ts b/services/apps/cache_worker/src/repo/segment.repo.ts new file mode 100644 index 0000000000..71a7bdccb0 --- /dev/null +++ b/services/apps/cache_worker/src/repo/segment.repo.ts @@ -0,0 +1,173 @@ +import { DbConnection, DbTransaction } from '@crowd/database' +import { Logger } from '@crowd/logging' +import { IDashboardCacheLastRefreshedAt, ISegment } from 'types' + +class SegmentRepository { + constructor( + private readonly connection: DbConnection | DbTransaction, + private readonly log: Logger, + ) {} + + async getAllSegments(tenantId: string, limit: number, offset: number): Promise { + let rows: ISegment[] = [] + try { + rows = await this.connection.query( + ` + select + id as "segmentId", + slug, + "parentSlug", + "grandparentSlug" + from segments + where "tenantId" = $(tenantId) + order by id asc + limit $(limit) + offset $(offset) + + `, + { + tenantId, + limit, + offset, + }, + ) + } catch (err) { + this.log.error('Error while getting all segments', err) + + throw new Error(err) + } + + return rows || [] + } + + // getProjectLeafSegments + async getProjectLeafSegments(parentSlug: string, tenantId: string): Promise { + let rows: ISegment[] = [] + try { + rows = await this.connection.query( + ` + select + id as "segmentId", + slug, + "parentSlug", + "grandparentSlug" + from segments + where "parentSlug" = $(parentSlug) + and "tenantId" = $(tenantId) + and slug is not null + and "grandparentSlug" is not null; + + `, + { + tenantId, + parentSlug, + }, + ) + } catch (err) { + this.log.error(`Error while getting leaf segments of project ${parentSlug}`, err) + + throw new Error(err) + } + + return rows || [] + } + + async getProjectGroupLeafSegments( + grandparentSlug: string, + tenantId: string, + ): Promise { + let rows: ISegment[] = [] + try { + rows = await this.connection.query( + ` + select + id as "segmentId", + slug, + "parentSlug", + "grandparentSlug" + from segments + where "grandparentSlug" = $(grandparentSlug) + and "tenantId" = $(tenantId) + and slug is not null + and "parentSlug" is not null; + + `, + { + tenantId, + grandparentSlug, + }, + ) + } catch (err) { + this.log.error(`Error while getting leaf segments of project group ${grandparentSlug}`, err) + + throw new Error(err) + } + + return rows || [] + } + + async getDefaultSegment(tenantId: string): Promise { + let result: ISegment + try { + result = await this.connection.oneOrNone( + ` + select + id as "segmentId", + slug, + "parentSlug", + "grandparentSlug" + from segments + where "tenantId" = $(tenantId) + and slug is not null + and "parentSlug" is not null + and "grandparentSlug" is not null; + + `, + { + tenantId, + }, + ) + } catch (err) { + this.log.error(`Error while getting the default segment of tenant ${tenantId}`, err) + + throw new Error(err) + } + + return result + } + + async getDashboardCacheLastRefreshedAt(segmentId: string): Promise { + try { + const result: IDashboardCacheLastRefreshedAt = await this.connection.oneOrNone( + ` + select "dashboardCacheLastRefreshedAt" + from segments + where "id" = $(segmentId);`, + { + segmentId, + }, + ) + return result?.dashboardCacheLastRefreshedAt + } catch (err) { + throw new Error(err) + } + } + + async updateDashboardCacheLastRefreshedAt(segmentId: string): Promise { + try { + await this.connection.any( + ` + update segments set "dashboardCacheLastRefreshedAt" = now() + where "id" = $(segmentId); + `, + { + segmentId, + }, + ) + } catch (err) { + throw new Error(err) + } + } +} + +export default SegmentRepository diff --git a/services/apps/cache_worker/src/repo/tenant.repo.ts b/services/apps/cache_worker/src/repo/tenant.repo.ts new file mode 100644 index 0000000000..8126db74df --- /dev/null +++ b/services/apps/cache_worker/src/repo/tenant.repo.ts @@ -0,0 +1,33 @@ +import { DbConnection, DbTransaction } from '@crowd/database' +import { Logger } from '@crowd/logging' +import { ITenant } from 'types' + +class TenantRepository { + constructor( + private readonly connection: DbConnection | DbTransaction, + private readonly log: Logger, + ) {} + + async getAllTenants(): Promise { + let rows: ITenant[] = [] + try { + rows = await this.connection.query(` + select + id as "tenantId", + plan + from tenants + where "deletedAt" is null + and plan IN ('Scale', 'Growth', 'Essential', 'Enterprise') + and ("trialEndsAt" > NOW() or "trialEndsAt" is null); + `) + } catch (err) { + this.log.error('Error while getting all tenants', err) + + throw new Error(err) + } + + return rows + } +} + +export default TenantRepository diff --git a/services/apps/cache_worker/src/types.ts b/services/apps/cache_worker/src/types.ts new file mode 100644 index 0000000000..389ffea644 --- /dev/null +++ b/services/apps/cache_worker/src/types.ts @@ -0,0 +1,110 @@ +import { CubeDimension, CubeGranularity, CubeMeasure, ICubeOrder } from '@crowd/cubejs' + +export interface ITenant { + tenantId: string + plan: string +} + +export interface ISegment { + segmentId: string + slug: string + parentSlug: string + grandparentSlug: string +} + +export interface IDashboardCacheLastRefreshedAt { + dashboardCacheLastRefreshedAt: string +} + +export interface IActiveMembersTimeseriesResult { + [CubeDimension.ACTIVITY_DATE_DAY]: string + [CubeDimension.ACTIVITY_DATE]: string + [CubeMeasure.MEMBER_COUNT]: string +} + +export interface INewMembersTimeseriesResult { + [CubeDimension.MEMBER_JOINED_AT_DAY]: string + [CubeDimension.MEMBER_JOINED_AT]: string + [CubeMeasure.MEMBER_COUNT]: string +} + +export interface INewOrganizationsTimeseriesResult { + [CubeDimension.ORGANIZATIONS_JOINED_AT_DAY]: string + [CubeDimension.ORGANIZATIONS_JOINED_AT]: string + [CubeMeasure.ORGANIZATION_COUNT]: string +} + +export interface IActiveOrganizationsTimeseriesResult { + [CubeDimension.ACTIVITY_DATE_DAY]: string + [CubeDimension.ACTIVITY_DATE]: string + [CubeMeasure.ORGANIZATION_COUNT]: string +} + +export interface IActivityTimeseriesResult { + [CubeDimension.ACTIVITY_DATE_DAY]: string + [CubeDimension.ACTIVITY_DATE]: string + [CubeMeasure.ACTIVITY_COUNT]: string +} + +export interface IActivityBySentimentMoodResult { + [CubeDimension.ACTIVITY_SENTIMENT_MOOD]: string +} + +export interface IActivityByTypeAndPlatformResult { + [CubeDimension.ACTIVITY_TYPE]: string + [CubeDimension.ACTIVITY_PLATFORM]: string + [CubeMeasure.ACTIVITY_COUNT]: string +} + +export interface IDashboardData { + activeMembers: { + total: number + previousPeriodTotal: number + timeseries: IActiveMembersTimeseriesResult[] + } + newMembers: { + total: number + previousPeriodTotal: number + timeseries: INewMembersTimeseriesResult[] + } + newOrganizations: { + total: number + previousPeriodTotal: number + timeseries: INewOrganizationsTimeseriesResult[] + } + activeOrganizations: { + total: number + previousPeriodTotal: number + timeseries: IActiveOrganizationsTimeseriesResult[] + } + activity: { + total: number + previousPeriodTotal: number + timeseries: IActivityTimeseriesResult[] + bySentimentMood: IActivityBySentimentMoodResult[] + byTypeAndPlatform: IActivityByTypeAndPlatformResult[] + } +} + +export interface ITimeframe { + startDate: string + endDate: string + previousPeriodStartDate: string + previousPeriodEndDate: string +} + +export interface ICubeQueryParams { + tenantId: string + segmentIds: string[] + startDate: string + endDate: string + granularity?: CubeGranularity | string + platform?: string + rawResult?: boolean + dimensions?: CubeDimension[] | string[] + order?: ICubeOrder +} + +export interface IPlatforms { + platforms: string[] +} diff --git a/services/apps/cache_worker/src/workflows.ts b/services/apps/cache_worker/src/workflows.ts new file mode 100644 index 0000000000..015766b58d --- /dev/null +++ b/services/apps/cache_worker/src/workflows.ts @@ -0,0 +1,5 @@ +import { refreshDashboardCache } from './workflows/refreshDashboardCache' + +import { spawnDashboardCacheRefreshForAllTenants } from './workflows/spawnDashboardCacheRefreshForAllTenants' + +export { spawnDashboardCacheRefreshForAllTenants, refreshDashboardCache } diff --git a/services/apps/cache_worker/src/workflows/refreshDashboardCache.ts b/services/apps/cache_worker/src/workflows/refreshDashboardCache.ts new file mode 100644 index 0000000000..1bad7916ae --- /dev/null +++ b/services/apps/cache_worker/src/workflows/refreshDashboardCache.ts @@ -0,0 +1,375 @@ +import { proxyActivities } from '@temporalio/workflow' + +import { IProcessRefreshDashboardCacheArgs } from '@crowd/types' +import * as activities from '../activities/dashboard-cache/refreshDashboardCache' + +import { + IActiveMembersTimeseriesResult, + IActiveOrganizationsTimeseriesResult, + IActivityBySentimentMoodResult, + IActivityByTypeAndPlatformResult, + IActivityTimeseriesResult, + IDashboardData, + INewMembersTimeseriesResult, + INewOrganizationsTimeseriesResult, + ITimeframe, +} from 'types' +import moment from 'moment' +import { DashboardTimeframe } from '../enums' + +const activity = proxyActivities({ + startToCloseTimeout: '3 minute', + retry: { maximumAttempts: 3 }, +}) + +export async function refreshDashboardCache( + args: IProcessRefreshDashboardCacheArgs, +): Promise { + const segmentsEnabled = args.segmentId ? true : false + + // if no segments were sent, set current segment as default one + if (!args.segmentId) { + const defaultSegment = await activity.getDefaultSegment(args.tenantId) + args.segmentId = defaultSegment.segmentId + args.leafSegmentIds = [defaultSegment.segmentId] + } + + const dashboardLastRefreshedAt = await activity.getDashboardCacheLastRefreshedAt(args.segmentId) + + const activePlatforms = await activity.getActivePlatforms(args.leafSegmentIds) + + const currentDate = new Date() + + // we should do a full refresh, when + // - segments are enabled (we only refresh once a day for segment enabled deploys, so no need for same-day optimizations) + // - dashboard wasn't refreshed before yet (ie: it's null) + // - day changed between now() and dashboardLastRefreshedAt, so we need to calculate the metrics for the new time range + if ( + segmentsEnabled || + !dashboardLastRefreshedAt || + currentDate.getUTCDate() !== new Date(dashboardLastRefreshedAt).getUTCDate() + ) { + // main view with no platform filter + await refreshDashboardCacheForAllTimeranges(args.tenantId, args.segmentId, args.leafSegmentIds) + + // for each platform also cache dashboard values + for (const platform of activePlatforms) { + await refreshDashboardCacheForAllTimeranges( + args.tenantId, + args.segmentId, + args.leafSegmentIds, + platform, + ) + } + } else { + // first check if there's a new activity between dashboardLastRefreshedAt and now() + const platforms = await activity.findNewActivityPlatforms( + dashboardLastRefreshedAt, + args.leafSegmentIds, + ) + + // only refresh the main view and returned platform views if there are new activities + if (platforms && platforms.length > 0) { + // refresh the main view + await refreshDashboardCacheForAllTimeranges( + args.tenantId, + args.segmentId, + args.leafSegmentIds, + ) + + for (const platform of platforms) { + await refreshDashboardCacheForAllTimeranges( + args.tenantId, + args.segmentId, + args.leafSegmentIds, + platform, + ) + } + } + } + + // update dashboardLastRefreshedAt + await activity.updateMemberMergeSuggestionsLastGeneratedAt(args.segmentId) +} + +async function refreshDashboardCacheForAllTimeranges( + tenantId: string, + segmentId: string, + leafSegmentIds: string[], + platform?: string, +) { + for (const timeframe in DashboardTimeframe) { + const data = await getDashboardCacheData( + tenantId, + leafSegmentIds, + DashboardTimeframe[timeframe], + platform, + ) + + // try saving it to cache + await activity.saveToCache(tenantId, segmentId, DashboardTimeframe[timeframe], data, platform) + } +} + +async function getDashboardCacheData( + tenantId: string, + segmentIds: string[], + timeframe: DashboardTimeframe, + platform?: string, +): Promise { + // build dateranges + const { startDate, endDate, previousPeriodStartDate, previousPeriodEndDate } = + buildTimeframe(timeframe) + + // new members total + const newMembersTotal = await activity.getNewMembers({ + tenantId, + segmentIds, + startDate, + endDate, + platform, + }) + + // new members previous period total + const newMembersPreviousPeriodTotal = await activity.getNewMembers({ + tenantId, + segmentIds, + startDate: previousPeriodStartDate, + endDate: previousPeriodEndDate, + platform, + }) + + // new members timeseries + const newMembersTimeseries = await activity.getNewMembers({ + tenantId, + segmentIds, + startDate, + endDate, + granularity: 'day', + platform, + rawResult: true, + }) + + // active members total + const activeMembersTotal = await activity.getActiveMembers({ + tenantId, + segmentIds, + startDate, + endDate, + platform, + }) + + // active members previous period total + const activeMembersPreviousPeriodTotal = await activity.getActiveMembers({ + tenantId, + segmentIds, + startDate: previousPeriodStartDate, + endDate: previousPeriodEndDate, + platform, + }) + + // active members timeseries + const activeMembersTimeseries = await activity.getActiveMembers( + { + tenantId, + segmentIds, + startDate, + endDate, + granularity: 'day', + platform, + rawResult: true, + }, + ) + + // new organizations total + const newOrganizationsTotal = await activity.getNewOrganizations({ + tenantId, + segmentIds, + startDate, + endDate, + platform, + }) + + // new organizations previous period total + const newOrganizationsPreviousPeriodTotal = await activity.getNewOrganizations({ + tenantId, + segmentIds, + startDate: previousPeriodStartDate, + endDate: previousPeriodEndDate, + platform, + }) + + // new organizations timeseries + const newOrganizationsTimeseries = await activity.getNewOrganizations< + INewOrganizationsTimeseriesResult[] + >({ + tenantId, + segmentIds, + startDate, + endDate, + granularity: 'day', + platform, + rawResult: true, + }) + + // active organizations total + const activeOrganizationsTotal = await activity.getActiveOrganizations({ + tenantId, + segmentIds, + startDate, + endDate, + platform, + }) + + // active organizations previous period total + const activeOrganizationsPreviousPeriodTotal = await activity.getActiveOrganizations({ + tenantId, + segmentIds, + startDate: previousPeriodStartDate, + endDate: previousPeriodEndDate, + platform, + }) + + // active organizations timeseries + const activeOrganizationsTimeseries = await activity.getActiveOrganizations< + IActiveOrganizationsTimeseriesResult[] + >({ + tenantId, + segmentIds, + startDate, + endDate, + granularity: 'day', + platform, + rawResult: true, + }) + + // activities total + const activitiesTotal = await activity.getActivities({ + tenantId, + segmentIds, + startDate, + endDate, + platform, + }) + + // activities previous period total + const activitiesPreviousPeriodTotal = await activity.getActivities({ + tenantId, + segmentIds, + startDate: previousPeriodStartDate, + endDate: previousPeriodEndDate, + platform, + }) + + // activities timeseries + const activitiesTimeseries = await activity.getActivities({ + tenantId, + segmentIds, + startDate, + endDate, + granularity: 'day', + platform, + rawResult: true, + }) + + // activities by sentiment mood + const activitiesBySentimentMood = await activity.getActivities({ + tenantId, + segmentIds, + startDate, + endDate, + dimensions: ['Activities.sentimentMood'], + platform, + rawResult: true, + }) + + // activities by type and platform + const activitiesByTypeAndPlatform = await activity.getActivities< + IActivityByTypeAndPlatformResult[] + >({ + tenantId, + segmentIds, + startDate, + endDate, + dimensions: ['Activities.platform', 'Activities.type'], + order: { 'Activities.count': 'desc' }, + platform, + rawResult: true, + }) + + return { + newMembers: { + total: newMembersTotal, + previousPeriodTotal: newMembersPreviousPeriodTotal, + timeseries: newMembersTimeseries, + }, + activeMembers: { + total: activeMembersTotal, + previousPeriodTotal: activeMembersPreviousPeriodTotal, + timeseries: activeMembersTimeseries, + }, + newOrganizations: { + total: newOrganizationsTotal, + previousPeriodTotal: newOrganizationsPreviousPeriodTotal, + timeseries: newOrganizationsTimeseries, + }, + activeOrganizations: { + total: activeOrganizationsTotal, + previousPeriodTotal: activeOrganizationsPreviousPeriodTotal, + timeseries: activeOrganizationsTimeseries, + }, + activity: { + total: activitiesTotal, + previousPeriodTotal: activitiesPreviousPeriodTotal, + timeseries: activitiesTimeseries, + bySentimentMood: activitiesBySentimentMood, + byTypeAndPlatform: activitiesByTypeAndPlatform, + }, + } +} + +function buildTimeframe(timeframe: DashboardTimeframe): ITimeframe { + if (timeframe === DashboardTimeframe.LAST_7_DAYS) { + const startDate = moment().subtract(6, 'days').startOf('day').toISOString() + const endDate = moment().endOf('day').toISOString() + const previousPeriodStartDate = moment().subtract(13, 'days').startOf('day').toISOString() + const previousPeriodEndDate = moment().subtract(7, 'days').endOf('day').toISOString() + + return { + startDate, + endDate, + previousPeriodStartDate, + previousPeriodEndDate, + } + } + + if (timeframe === DashboardTimeframe.LAST_14_DAYS) { + const startDate = moment().subtract(13, 'days').startOf('day').toISOString() + const endDate = moment().endOf('day').toISOString() + const previousPeriodStartDate = moment().subtract(27, 'days').startOf('day').toISOString() + const previousPeriodEndDate = moment().subtract(14, 'days').endOf('day').toISOString() + + return { + startDate, + endDate, + previousPeriodStartDate, + previousPeriodEndDate, + } + } + + if (timeframe === DashboardTimeframe.LAST_30_DAYS) { + const startDate = moment().subtract(29, 'days').startOf('day').toISOString() + const endDate = moment().endOf('day').toISOString() + const previousPeriodStartDate = moment().subtract(59, 'days').startOf('day').toISOString() + const previousPeriodEndDate = moment().subtract(30, 'days').endOf('day').toISOString() + + return { + startDate, + endDate, + previousPeriodStartDate, + previousPeriodEndDate, + } + } + + throw new Error(`Unsupported timerange ${timeframe}!`) +} diff --git a/services/apps/cache_worker/src/workflows/spawnDashboardCacheRefreshForAllTenants.ts b/services/apps/cache_worker/src/workflows/spawnDashboardCacheRefreshForAllTenants.ts new file mode 100644 index 0000000000..403725ed92 --- /dev/null +++ b/services/apps/cache_worker/src/workflows/spawnDashboardCacheRefreshForAllTenants.ts @@ -0,0 +1,126 @@ +import { + proxyActivities, + startChild, + ParentClosePolicy, + ChildWorkflowCancellationType, + workflowInfo, + executeChild, +} from '@temporalio/workflow' + +import * as activities from '../activities/getTenantSegmentInfo' +import { refreshDashboardCache } from './refreshDashboardCache' +import { ISegment } from 'types' + +const activity = proxyActivities({ startToCloseTimeout: '1 minute' }) + +export async function spawnDashboardCacheRefreshForAllTenants(): Promise { + const tenants = await activity.getAllTenants() + const segmentsEnabled = await activity.isSegmentsEnabled() + const info = workflowInfo() + + if (segmentsEnabled) { + // we should spawn refreshDashboardCache for each tenant-segment couples + + const SEGMENT_PAGE_SIZE = 250 + + for (const tenant of tenants) { + // get all segments in tenant + let offset = 0 + let segments: ISegment[] + const segmentLeafIdMap = new Map() + + do { + segments = await activity.getAllSegments(tenant.tenantId, SEGMENT_PAGE_SIZE, offset) + + // find each segment's associated leaf segment + for (const segment of segments) { + if (segment.slug && segment.parentSlug && segment.grandparentSlug) { + // it's already a leaf segment, add itself to leaf segment id map + segmentLeafIdMap.set(segment.segmentId, [segment.segmentId]) + } else if (segment.slug && segment.parentSlug && !segment.grandparentSlug) { + // it's a parent segment, find its leafs + const leafs = await activity.getProjectLeafSegments(segment.slug, tenant.tenantId) + if (leafs && leafs.length > 0) { + segmentLeafIdMap.set( + segment.segmentId, + leafs.map((l) => l.segmentId), + ) + } + } else if (segment.slug && !segment.parentSlug && !segment.grandparentSlug) { + // it's a grandparent segment, find its leafs + const leafs = await activity.getProjectGroupLeafSegments(segment.slug, tenant.tenantId) + if (leafs && leafs.length > 0) { + segmentLeafIdMap.set( + segment.segmentId, + leafs.map((l) => l.segmentId), + ) + } + } + } + + offset += SEGMENT_PAGE_SIZE + } while (segments.length > 0) + + // execute each child with batcheds of 50 + const CHUNK_SIZE = 50 + const entries = [...segmentLeafIdMap] // Convert map entries into an Array + const chunked: Map[] = [] + + for (let i = 0; i < entries.length; i += CHUNK_SIZE) { + const chunk = new Map(entries.slice(i, i + CHUNK_SIZE)) // Create new Map(s) with the chunked entries + chunked.push(chunk) + } + + for (const chunk of chunked) { + // create a workflow for each tenantId-segmentId couple + await Promise.all( + Array.from(chunk).map(([segmentId, leafSegmentIds]) => { + return executeChild(refreshDashboardCache, { + workflowId: `${info.workflowId}/${tenant.tenantId}/${segmentId}`, + cancellationType: ChildWorkflowCancellationType.ABANDON, + parentClosePolicy: ParentClosePolicy.PARENT_CLOSE_POLICY_ABANDON, + retry: { + backoffCoefficient: 2, + initialInterval: 2 * 1000, + maximumInterval: 30 * 1000, + }, + args: [ + { + tenantId: tenant.tenantId, + segmentId, + leafSegmentIds, + }, + ], + searchAttributes: { + TenantId: [tenant.tenantId], + }, + }) + }), + ) + } + } + } else { + await Promise.all( + tenants.map((tenant) => { + return startChild(refreshDashboardCache, { + workflowId: `${info.workflowId}/${tenant.tenantId}`, + cancellationType: ChildWorkflowCancellationType.ABANDON, + parentClosePolicy: ParentClosePolicy.PARENT_CLOSE_POLICY_ABANDON, + retry: { + backoffCoefficient: 2, + initialInterval: 2 * 1000, + maximumInterval: 30 * 1000, + }, + args: [ + { + tenantId: tenant.tenantId, + }, + ], + searchAttributes: { + TenantId: [tenant.tenantId], + }, + }) + }), + ) + } +} diff --git a/services/apps/cache_worker/tsconfig.json b/services/apps/cache_worker/tsconfig.json new file mode 100644 index 0000000000..e20e712429 --- /dev/null +++ b/services/apps/cache_worker/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "target": "es2017", + "module": "Node16", + "lib": ["es6", "es7", "es2017", "es2017.object", "es2015.promise", "ES2021.String"], + "skipLibCheck": true, + "sourceMap": true, + "moduleResolution": "node16", + "experimentalDecorators": true, + "esModuleInterop": true, + "baseUrl": "./src", + "paths": { + "@crowd/*": ["../../../libs/*/src"], + "@crowd/archetype-*": ["../../../archetypes/*/src"] + } + }, + "include": ["src/**/*"] +} diff --git a/services/apps/data_sink_worker/config/custom-environment-variables.json b/services/apps/data_sink_worker/config/custom-environment-variables.json index c5650ac796..02f160ff35 100644 --- a/services/apps/data_sink_worker/config/custom-environment-variables.json +++ b/services/apps/data_sink_worker/config/custom-environment-variables.json @@ -39,5 +39,8 @@ }, "searchSyncApi": { "baseUrl": "CROWD_SEARCH_SYNC_API_URL" + }, + "worker": { + "queuePriorityLevel": "QUEUE_PRIORITY_LEVEL" } } diff --git a/services/apps/data_sink_worker/config/default.json b/services/apps/data_sink_worker/config/default.json index e9a6b31829..37208be81c 100644 --- a/services/apps/data_sink_worker/config/default.json +++ b/services/apps/data_sink_worker/config/default.json @@ -7,6 +7,7 @@ "automationsTaskQueue": "automations" }, "worker": { - "maxStreamRetries": 5 + "maxStreamRetries": 5, + "queuePriorityLevel": "normal" } } diff --git a/services/apps/data_sink_worker/package.json b/services/apps/data_sink_worker/package.json index 349e1cd4a0..7881889fd0 100644 --- a/services/apps/data_sink_worker/package.json +++ b/services/apps/data_sink_worker/package.json @@ -18,6 +18,7 @@ "script:restart-result": "SERVICE=script TS_NODE_TRANSPILE_ONLY=true node -r tsconfig-paths/register -r ts-node/register src/bin/restart-result.ts", "script:process-results": "SERVICE=script TS_NODE_TRANSPILE_ONLY=true node -r tsconfig-paths/register -r ts-node/register src/bin/process-results.ts", "script:map-tenant-members-to-org": "SERVICE=script TS_NODE_TRANSPILE_ONLY=true node -r tsconfig-paths/register -r ts-node/register src/bin/map-tenant-members-to-org.ts", + "script:fix-org-cache-identities-duplicates": "SERVICE=script TS_NODE_TRANSPILE_ONLY=true node -r tsconfig-paths/register -r ts-node/register src/bin/fix-org-cache-identities-duplicates.ts", "script:map-member-to-org": "SERVICE=script TS_NODE_TRANSPILE_ONLY=true node -r tsconfig-paths/register -r ts-node/register src/bin/map-member-to-org.ts" }, "dependencies": { @@ -34,6 +35,7 @@ "@crowd/types": "file:../../libs/types", "@crowd/feature-flags": "file:../../libs/feature-flags", "@crowd/temporal": "file:../../libs/temporal", + "@crowd/common_services": "file:../../libs/common_services", "@crowd/telemetry": "file:../../libs/telemetry", "@types/config": "^3.3.0", "@types/node": "^18.16.3", @@ -42,6 +44,8 @@ "lodash.isequal": "^4.5.0", "lodash.mergewith": "^4.6.2", "lodash.uniqby": "^4.7.0", + "moment": "2.29.4", + "moment-timezone": "^0.5.34", "ts-node": "^10.9.1", "tsconfig-paths": "^4.2.0", "typescript": "^5.0.4" diff --git a/services/apps/data_sink_worker/src/bin/fix-org-cache-identities-duplicates.ts b/services/apps/data_sink_worker/src/bin/fix-org-cache-identities-duplicates.ts new file mode 100644 index 0000000000..40621c2e51 --- /dev/null +++ b/services/apps/data_sink_worker/src/bin/fix-org-cache-identities-duplicates.ts @@ -0,0 +1,257 @@ +import { + DbConnection, + DbInstance, + DbTransaction, + RepositoryBase, + getDbConnection, + getDbInstance, +} from '@crowd/database' +import { getServiceLogger } from '@crowd/logging' +import { DB_CONFIG } from '../conf' + +/* eslint-disable @typescript-eslint/no-explicit-any */ + +interface IOrgCacheToMerge { + name: string + data: { + id: string + website: string + }[] +} + +async function getOrganizationsToFix(db: DbConnection): Promise { + const results = await db.any( + ` + select name, + json_agg(json_build_object( + 'id', id, + 'website', website + )) as data + from "organizationCacheIdentities" + group by name + having count(id) > 1; +`, + ) + + return results +} + +async function getOrganizationCaches(db: DbConnection, ids: string[]): Promise { + const results = await db.any( + ` +select * +from "organizationCaches" +where id in ($(ids:csv)) +`, + { ids }, + ) + + return results +} + +async function updateCacheIdentityWebsite( + db: DbTransaction, + id: string, + website: string, +): Promise { + await db.none(`update "organizationCacheIdentities" set website = $(website) where id = $(id)`, { + id, + website, + }) +} + +async function moveLinksToNewCacheId( + db: DbTransaction, + fromIds: string[], + toId: string, +): Promise { + const existingLinks = await db.any( + ` + select "organizationId", "organizationCacheId" from "organizationCacheLinks" + where "organizationCacheId" in ($(ids:csv)) + `, + { + ids: fromIds.concat([toId]), + }, + ) + + const toLinks = existingLinks.filter((l) => l.organizationCacheId === toId) + const toRemove: any[] = [] + const toMove: any[] = [] + for (const fromId of fromIds) { + const fromIdLinks = existingLinks.filter((l) => l.organizationCacheId === fromId) + for (const fromIdLink of fromIdLinks) { + // if we already have a link to the same organization we can just remove the old link + // otherwise we need to move the link to the new cache id + if (toLinks.find((l) => l.organizationId === fromIdLink.organizationId)) { + toRemove.push(fromIdLink) + } else { + toMove.push(fromIdLink) + } + } + } + + for (const link of toRemove) { + await db.none( + `delete from "organizationCacheLinks" where "organizationId" = $(organizationId) and "organizationCacheId" = $(organizationCacheId)`, + { + organizationId: link.organizationId, + organizationCacheId: link.organizationCacheId, + }, + ) + } + + for (const link of toMove) { + await db.none( + `update "organizationCacheLinks" set "organizationCacheId" = $(toId) where "organizationId" = $(organizationId) and "organizationCacheId" = $(organizationCacheId)`, + { + organizationId: link.organizationId, + organizationCacheId: link.organizationCacheId, + toId, + }, + ) + } +} + +async function removeCaches(db: DbTransaction, ids: string[]): Promise { + await db.none(`delete from "organizationCaches" where id in ($(ids:csv))`, { ids }) +} + +async function removeCacheIdentities(db: DbTransaction, ids: string[]): Promise { + await db.none(`delete from "organizationCacheIdentities" where id in ($(ids:csv))`, { ids }) +} + +const columnsToIgnore = [ + 'id', + 'createdAt', + 'updatedAt', + 'deletedAt', + 'enriched', + 'lastEnrichedAt', + 'manuallyCreated', + 'oldName', + 'oldWebsite', +] + +async function updateOrganizationCacheData(dbInstance, db, id, data) { + const keys = Object.keys(data).filter((k) => !columnsToIgnore.includes(k)) + + if (keys.length !== 0) { + const dynamicColumnSet = new dbInstance.helpers.ColumnSet(keys, { + table: 'organizationCaches', + }) + + if (data.naics) { + data.naics = JSON.stringify(data.naics) + } + + const prepared = RepositoryBase.prepare(data, dynamicColumnSet) + const query = dbInstance.helpers.update(prepared, dynamicColumnSet) + + const condition = dbInstance.as.format('where id = $(id)', { id }) + const result = await db.result(`${query} ${condition}`) + + if (result.rowCount !== 1) { + throw new Error('Updated row count not equal to 1!') + } + } +} + +const log = getServiceLogger() + +async function processOrgCache( + db: DbConnection, + dbInstance: DbInstance, + result: IOrgCacheToMerge, +): Promise { + const ids = result.data.map((d) => d.id) + + const caches = await getOrganizationCaches(db, ids) + + if (ids.length > 1) { + // need to merge all datapoints together + if (ids.length !== caches.length) { + throw new Error(`Did not find all org cache entries for these ids: [${ids.join(', ')}]`) + } + + // pick the most completed entry + let index = 0 + let max = 0 + for (let i = 0; i < caches.length; i++) { + const filledKeys = Object.keys(caches[i]).filter( + (k) => !columnsToIgnore.includes(k) && caches[i][k] !== null, + ) + + if (filledKeys.length > max) { + max = filledKeys.length + index = i + } + } + + const data = caches[index] + + const toUpdate: any = {} + for (let i = 0; i < caches.length; i++) { + if (i === index) { + continue + } + for (const key of Object.keys(data)) { + if (data[key] === null && caches[i][key] !== null) { + toUpdate[key] = caches[i][key] + } + } + } + + try { + await db.tx(async (tx) => { + if (Object.keys(toUpdate).length > 0) { + await updateOrganizationCacheData(dbInstance, tx, data.id, toUpdate) + } + const cacheIdsToRemove = caches.filter((c) => c.id !== data.id).map((c) => c.id) + + await moveLinksToNewCacheId(tx, cacheIdsToRemove, data.id) + await removeCacheIdentities(tx, cacheIdsToRemove) + + // do we need to set the website? + const website = result.data + .filter((d) => d.id !== data.id) + .reduce((prev, curr) => { + if (!prev || prev === '') { + return curr.website + } + }, '') + + if (website && website !== '') { + await updateCacheIdentityWebsite(tx, data.id, website) + } + + await removeCaches(tx, cacheIdsToRemove) + }) + } catch (err) { + log.error(err, { id: data.id }, 'Error while processing organization caches!') + throw err + } + } else { + throw new Error('should not happen') + } +} + +setImmediate(async () => { + const db = await getDbConnection(DB_CONFIG()) + const dbInstance = getDbInstance() + + let results = await getOrganizationsToFix(db) + + let count = 0 + while (results.length > 0) { + for (const result of results) { + await processOrgCache(db, dbInstance, result) + count++ + log.info({ count }, `Processed org cache!`) + } + + results = await getOrganizationsToFix(db) + } + + process.exit(0) +}) diff --git a/services/apps/data_sink_worker/src/bin/map-member-to-org.ts b/services/apps/data_sink_worker/src/bin/map-member-to-org.ts index 9b4e9b281f..13d15cb168 100644 --- a/services/apps/data_sink_worker/src/bin/map-member-to-org.ts +++ b/services/apps/data_sink_worker/src/bin/map-member-to-org.ts @@ -2,12 +2,7 @@ import { DB_CONFIG, REDIS_CONFIG, SQS_CONFIG, TEMPORAL_CONFIG, UNLEASH_CONFIG } import { DbStore, getDbConnection } from '@crowd/database' import { getServiceTracer } from '@crowd/tracing' import { getServiceLogger } from '@crowd/logging' -import { - DataSinkWorkerEmitter, - NodejsWorkerEmitter, - SearchSyncWorkerEmitter, - getSqsClient, -} from '@crowd/sqs' +import { getSqsClient } from '@crowd/sqs' import MemberRepository from '../repo/member.repo' import MemberService from '../service/member.service' import DataSinkRepository from '../repo/dataSink.repo' @@ -15,6 +10,13 @@ import { OrganizationService } from '../service/organization.service' import { getUnleashClient } from '@crowd/feature-flags' import { Client as TemporalClient, getTemporalClient } from '@crowd/temporal' import { getRedisClient } from '@crowd/redis' +import { + DataSinkWorkerEmitter, + NodejsWorkerEmitter, + PriorityLevelContextRepository, + QueuePriorityContextLoader, + SearchSyncWorkerEmitter, +} from '@crowd/common_services' const tracer = getServiceTracer() const log = getServiceLogger() @@ -37,31 +39,49 @@ setImmediate(async () => { temporal = await getTemporalClient(TEMPORAL_CONFIG()) } - const sqsClient = getSqsClient(SQS_CONFIG()) - const emitter = new DataSinkWorkerEmitter(sqsClient, tracer, log) - await emitter.init() + const redis = await getRedisClient(REDIS_CONFIG()) const dbConnection = await getDbConnection(DB_CONFIG()) const store = new DbStore(log, dbConnection) + const priorityLevelRepo = new PriorityLevelContextRepository(store, log) + const loader: QueuePriorityContextLoader = (tenantId: string) => + priorityLevelRepo.loadPriorityLevelContext(tenantId) + + const sqsClient = getSqsClient(SQS_CONFIG()) + const emitter = new DataSinkWorkerEmitter(sqsClient, redis, tracer, unleash, loader, log) + await emitter.init() + const dataSinkRepo = new DataSinkRepository(store, log) const memberRepo = new MemberRepository(store, log) - const nodejsWorkerEmitter = new NodejsWorkerEmitter(sqsClient, tracer, log) + const nodejsWorkerEmitter = new NodejsWorkerEmitter( + sqsClient, + redis, + tracer, + unleash, + loader, + log, + ) await nodejsWorkerEmitter.init() - const searchSyncWorkerEmitter = new SearchSyncWorkerEmitter(sqsClient, tracer, log) + const searchSyncWorkerEmitter = new SearchSyncWorkerEmitter( + sqsClient, + redis, + tracer, + unleash, + loader, + log, + ) await searchSyncWorkerEmitter.init() - const redisClient = await getRedisClient(REDIS_CONFIG()) - const memberService = new MemberService( store, nodejsWorkerEmitter, searchSyncWorkerEmitter, unleash, temporal, - redisClient, + redis, log, ) const orgService = new OrganizationService(store, log) @@ -93,10 +113,10 @@ setImmediate(async () => { orgService.addToMember(member.tenantId, segmentId, member.id, orgs) for (const org of orgs) { - await searchSyncWorkerEmitter.triggerOrganizationSync(member.tenantId, org.id) + await searchSyncWorkerEmitter.triggerOrganizationSync(member.tenantId, org.id, true) } - await searchSyncWorkerEmitter.triggerMemberSync(member.tenantId, member.id) + await searchSyncWorkerEmitter.triggerMemberSync(member.tenantId, member.id, true) log.info('Done mapping member to organizations!') } else { log.info('No organizations found with matching email domains!') diff --git a/services/apps/data_sink_worker/src/bin/map-tenant-members-to-org.ts b/services/apps/data_sink_worker/src/bin/map-tenant-members-to-org.ts index ff656b2d6c..bb273a5113 100644 --- a/services/apps/data_sink_worker/src/bin/map-tenant-members-to-org.ts +++ b/services/apps/data_sink_worker/src/bin/map-tenant-members-to-org.ts @@ -2,12 +2,7 @@ import { DB_CONFIG, REDIS_CONFIG, SQS_CONFIG, TEMPORAL_CONFIG, UNLEASH_CONFIG } import { DbStore, getDbConnection } from '@crowd/database' import { getServiceTracer } from '@crowd/tracing' import { getServiceLogger } from '@crowd/logging' -import { - DataSinkWorkerEmitter, - NodejsWorkerEmitter, - SearchSyncWorkerEmitter, - getSqsClient, -} from '@crowd/sqs' +import { getSqsClient } from '@crowd/sqs' import MemberRepository from '../repo/member.repo' import DataSinkRepository from '../repo/dataSink.repo' import MemberService from '../service/member.service' @@ -15,6 +10,13 @@ import { OrganizationService } from '../service/organization.service' import { getUnleashClient } from '@crowd/feature-flags' import { Client as TemporalClient, getTemporalClient } from '@crowd/temporal' import { getRedisClient } from '@crowd/redis' +import { + DataSinkWorkerEmitter, + NodejsWorkerEmitter, + PriorityLevelContextRepository, + QueuePriorityContextLoader, + SearchSyncWorkerEmitter, +} from '@crowd/common_services' const tracer = getServiceTracer() const log = getServiceLogger() @@ -37,34 +39,52 @@ setImmediate(async () => { temporal = await getTemporalClient(TEMPORAL_CONFIG()) } - const sqsClient = getSqsClient(SQS_CONFIG()) - const emitter = new DataSinkWorkerEmitter(sqsClient, tracer, log) - await emitter.init() - const dbConnection = await getDbConnection(DB_CONFIG()) const store = new DbStore(log, dbConnection) + const priorityLevelRepo = new PriorityLevelContextRepository(new DbStore(log, dbConnection), log) + const loader: QueuePriorityContextLoader = (tenantId: string) => + priorityLevelRepo.loadPriorityLevelContext(tenantId) + + const redis = await getRedisClient(REDIS_CONFIG()) + + const sqsClient = getSqsClient(SQS_CONFIG()) + const emitter = new DataSinkWorkerEmitter(sqsClient, redis, tracer, unleash, loader, log) + await emitter.init() + const dataSinkRepo = new DataSinkRepository(store, log) const memberRepo = new MemberRepository(store, log) const segmentIds = await dataSinkRepo.getSegmentIds(tenantId) const segmentId = segmentIds[segmentIds.length - 1] // leaf segment id - const nodejsWorkerEmitter = new NodejsWorkerEmitter(sqsClient, tracer, log) + const nodejsWorkerEmitter = new NodejsWorkerEmitter( + sqsClient, + redis, + tracer, + unleash, + loader, + log, + ) await nodejsWorkerEmitter.init() - const searchSyncWorkerEmitter = new SearchSyncWorkerEmitter(sqsClient, tracer, log) + const searchSyncWorkerEmitter = new SearchSyncWorkerEmitter( + sqsClient, + redis, + tracer, + unleash, + loader, + log, + ) await searchSyncWorkerEmitter.init() - const redisClient = await getRedisClient(REDIS_CONFIG()) - const memberService = new MemberService( store, nodejsWorkerEmitter, searchSyncWorkerEmitter, unleash, temporal, - redisClient, + redis, log, ) const orgService = new OrganizationService(store, log) @@ -107,10 +127,10 @@ setImmediate(async () => { orgService.addToMember(tenantId, segmentId, member.id, orgs) for (const org of orgs) { - await searchSyncWorkerEmitter.triggerOrganizationSync(tenantId, org.id) + await searchSyncWorkerEmitter.triggerOrganizationSync(tenantId, org.id, true) } - await searchSyncWorkerEmitter.triggerMemberSync(tenantId, member.id) + await searchSyncWorkerEmitter.triggerMemberSync(tenantId, member.id, true) } } diff --git a/services/apps/data_sink_worker/src/bin/process-results.ts b/services/apps/data_sink_worker/src/bin/process-results.ts index 19f320f150..11056cd036 100644 --- a/services/apps/data_sink_worker/src/bin/process-results.ts +++ b/services/apps/data_sink_worker/src/bin/process-results.ts @@ -12,15 +12,17 @@ import { DbStore, getDbConnection } from '@crowd/database' import { getServiceTracer } from '@crowd/tracing' import { getServiceLogger } from '@crowd/logging' import { getRedisClient } from '@crowd/redis' -import { - NodejsWorkerEmitter, - SearchSyncWorkerEmitter, - DataSinkWorkerEmitter, - getSqsClient, -} from '@crowd/sqs' +import { getSqsClient } from '@crowd/sqs' import { initializeSentimentAnalysis } from '@crowd/sentiment' import { getUnleashClient } from '@crowd/feature-flags' import { Client as TemporalClient, getTemporalClient } from '@crowd/temporal' +import { + DataSinkWorkerEmitter, + NodejsWorkerEmitter, + PriorityLevelContextRepository, + QueuePriorityContextLoader, + SearchSyncWorkerEmitter, +} from '@crowd/common_services' const tracer = getServiceTracer() const log = getServiceLogger() @@ -44,28 +46,52 @@ setImmediate(async () => { } const sqsClient = getSqsClient(SQS_CONFIG()) - const redisClient = await getRedisClient(REDIS_CONFIG()) + const redis = await getRedisClient(REDIS_CONFIG()) + const dbConnection = await getDbConnection(DB_CONFIG()) + const store = new DbStore(log, dbConnection) + + const priorityLevelRepo = new PriorityLevelContextRepository(new DbStore(log, dbConnection), log) + const loader: QueuePriorityContextLoader = (tenantId: string) => + priorityLevelRepo.loadPriorityLevelContext(tenantId) initializeSentimentAnalysis(SENTIMENT_CONFIG()) - const nodejsWorkerEmitter = new NodejsWorkerEmitter(sqsClient, tracer, log) + const nodejsWorkerEmitter = new NodejsWorkerEmitter( + sqsClient, + redis, + tracer, + unleash, + loader, + log, + ) await nodejsWorkerEmitter.init() - const searchSyncWorkerEmitter = new SearchSyncWorkerEmitter(sqsClient, tracer, log) + const searchSyncWorkerEmitter = new SearchSyncWorkerEmitter( + sqsClient, + redis, + tracer, + unleash, + loader, + log, + ) await searchSyncWorkerEmitter.init() - const dataSinkWorkerEmitter = new DataSinkWorkerEmitter(sqsClient, tracer, log) + const dataSinkWorkerEmitter = new DataSinkWorkerEmitter( + sqsClient, + redis, + tracer, + unleash, + loader, + log, + ) await dataSinkWorkerEmitter.init() - const dbConnection = await getDbConnection(DB_CONFIG()) - const store = new DbStore(log, dbConnection) - const service = new DataSinkService( store, nodejsWorkerEmitter, searchSyncWorkerEmitter, dataSinkWorkerEmitter, - redisClient, + redis, unleash, temporal, log, diff --git a/services/apps/data_sink_worker/src/bin/restart-all-failed-results.ts b/services/apps/data_sink_worker/src/bin/restart-all-failed-results.ts index 180add16b7..dc2b69efc4 100644 --- a/services/apps/data_sink_worker/src/bin/restart-all-failed-results.ts +++ b/services/apps/data_sink_worker/src/bin/restart-all-failed-results.ts @@ -1,11 +1,18 @@ -import { DB_CONFIG, SQS_CONFIG } from '../conf' +import { DB_CONFIG, REDIS_CONFIG, SQS_CONFIG, UNLEASH_CONFIG } from '../conf' import DataSinkRepository from '../repo/dataSink.repo' import { partition } from '@crowd/common' import { DbStore, getDbConnection } from '@crowd/database' import { getServiceTracer } from '@crowd/tracing' import { getServiceLogger } from '@crowd/logging' -import { DataSinkWorkerEmitter, getSqsClient } from '@crowd/sqs' +import { getSqsClient } from '@crowd/sqs' import { ProcessIntegrationResultQueueMessage } from '@crowd/types' +import { + DataSinkWorkerEmitter, + PriorityLevelContextRepository, + QueuePriorityContextLoader, +} from '@crowd/common_services' +import { getUnleashClient } from '@crowd/feature-flags' +import { getRedisClient } from '@crowd/redis' const batchSize = 500 @@ -13,12 +20,19 @@ const tracer = getServiceTracer() const log = getServiceLogger() setImmediate(async () => { - const sqsClient = getSqsClient(SQS_CONFIG()) - const emitter = new DataSinkWorkerEmitter(sqsClient, tracer, log) - await emitter.init() - + const unleash = await getUnleashClient(UNLEASH_CONFIG()) const dbConnection = await getDbConnection(DB_CONFIG()) const store = new DbStore(log, dbConnection) + const redis = await getRedisClient(REDIS_CONFIG()) + + const priorityLevelRepo = new PriorityLevelContextRepository(new DbStore(log, dbConnection), log) + const loader: QueuePriorityContextLoader = (tenantId: string) => + priorityLevelRepo.loadPriorityLevelContext(tenantId) + + const sqsClient = getSqsClient(SQS_CONFIG()) + + const emitter = new DataSinkWorkerEmitter(sqsClient, redis, tracer, unleash, loader, log) + await emitter.init() const repo = new DataSinkRepository(store, log) let count = 0 @@ -29,6 +43,7 @@ setImmediate(async () => { const messages = results.map((r) => { return { + tenantId: r.tenantId, payload: new ProcessIntegrationResultQueueMessage(r.id), groupId: r.id, deduplicationId: r.id, @@ -37,7 +52,7 @@ setImmediate(async () => { const batches = partition(messages, 10) for (const batch of batches) { - await emitter.sendMessages(batch) + await emitter.sendMessagesBatch(batch) } count += results.length diff --git a/services/apps/data_sink_worker/src/bin/restart-failed-results.ts b/services/apps/data_sink_worker/src/bin/restart-failed-results.ts index 3bb51b7912..945c4ec88a 100644 --- a/services/apps/data_sink_worker/src/bin/restart-failed-results.ts +++ b/services/apps/data_sink_worker/src/bin/restart-failed-results.ts @@ -1,10 +1,16 @@ -import { DB_CONFIG, SQS_CONFIG } from '../conf' +import { DB_CONFIG, REDIS_CONFIG, SQS_CONFIG, UNLEASH_CONFIG } from '../conf' import DataSinkRepository from '../repo/dataSink.repo' import { DbStore, getDbConnection } from '@crowd/database' import { getServiceTracer } from '@crowd/tracing' import { getServiceLogger } from '@crowd/logging' -import { DataSinkWorkerEmitter, getSqsClient } from '@crowd/sqs' -import { ProcessIntegrationResultQueueMessage } from '@crowd/types' +import { getSqsClient } from '@crowd/sqs' +import { getUnleashClient } from '@crowd/feature-flags' +import { getRedisClient } from '@crowd/redis' +import { + DataSinkWorkerEmitter, + PriorityLevelContextRepository, + QueuePriorityContextLoader, +} from '@crowd/common_services' const tracer = getServiceTracer() const log = getServiceLogger() @@ -19,13 +25,21 @@ if (processArguments.length !== 1) { const runId = processArguments[0] setImmediate(async () => { - const sqsClient = getSqsClient(SQS_CONFIG()) - const emitter = new DataSinkWorkerEmitter(sqsClient, tracer, log) - await emitter.init() - const dbConnection = await getDbConnection(DB_CONFIG()) const store = new DbStore(log, dbConnection) + const priorityLevelRepo = new PriorityLevelContextRepository(new DbStore(log, dbConnection), log) + const loader: QueuePriorityContextLoader = (tenantId: string) => + priorityLevelRepo.loadPriorityLevelContext(tenantId) + + const unleash = await getUnleashClient(UNLEASH_CONFIG()) + + const redis = await getRedisClient(REDIS_CONFIG()) + + const sqsClient = getSqsClient(SQS_CONFIG()) + const emitter = new DataSinkWorkerEmitter(sqsClient, redis, tracer, unleash, loader, log) + await emitter.init() + const repo = new DataSinkRepository(store, log) let results = await repo.getFailedResultsForRun(runId, 1, 20) @@ -33,9 +47,13 @@ setImmediate(async () => { await repo.resetResults(results.map((r) => r.id)) for (const result of results) { - await emitter.sendMessage( - `results-${result.tenantId}-${result.platform}`, - new ProcessIntegrationResultQueueMessage(result.id), + await emitter.triggerResultProcessing( + result.tenantId, + result.platform, + result.id, + result.id, + result.onboarding === null ? true : result.onboarding, + result.id, ) } diff --git a/services/apps/data_sink_worker/src/bin/restart-result.ts b/services/apps/data_sink_worker/src/bin/restart-result.ts index b945973657..b83fbd9051 100644 --- a/services/apps/data_sink_worker/src/bin/restart-result.ts +++ b/services/apps/data_sink_worker/src/bin/restart-result.ts @@ -1,10 +1,16 @@ -import { DB_CONFIG, SQS_CONFIG } from '../conf' +import { DB_CONFIG, REDIS_CONFIG, SQS_CONFIG, UNLEASH_CONFIG } from '../conf' import DataSinkRepository from '../repo/dataSink.repo' import { DbStore, getDbConnection } from '@crowd/database' import { getServiceTracer } from '@crowd/tracing' import { getServiceLogger } from '@crowd/logging' -import { DataSinkWorkerEmitter, getSqsClient } from '@crowd/sqs' -import { ProcessIntegrationResultQueueMessage } from '@crowd/types' +import { getSqsClient } from '@crowd/sqs' +import { + DataSinkWorkerEmitter, + PriorityLevelContextRepository, + QueuePriorityContextLoader, +} from '@crowd/common_services' +import { getUnleashClient } from '@crowd/feature-flags' +import { getRedisClient } from '@crowd/redis' const tracer = getServiceTracer() const log = getServiceLogger() @@ -19,13 +25,20 @@ if (processArguments.length !== 1) { const resultIds = processArguments[0].split(',') setImmediate(async () => { - const sqsClient = getSqsClient(SQS_CONFIG()) - const emitter = new DataSinkWorkerEmitter(sqsClient, tracer, log) - await emitter.init() - const dbConnection = await getDbConnection(DB_CONFIG()) const store = new DbStore(log, dbConnection) + const unleash = await getUnleashClient(UNLEASH_CONFIG()) + const redis = await getRedisClient(REDIS_CONFIG()) + + const priorityLevelRepo = new PriorityLevelContextRepository(new DbStore(log, dbConnection), log) + const loader: QueuePriorityContextLoader = (tenantId: string) => + priorityLevelRepo.loadPriorityLevelContext(tenantId) + + const sqsClient = getSqsClient(SQS_CONFIG()) + const emitter = new DataSinkWorkerEmitter(sqsClient, redis, tracer, unleash, loader, log) + await emitter.init() + const repo = new DataSinkRepository(store, log) for (const resultId of resultIds) { const result = await repo.getResultInfo(resultId) @@ -34,9 +47,12 @@ setImmediate(async () => { process.exit(1) } else { await repo.resetResults([resultId]) - await emitter.sendMessage( - `results-${result.tenantId}-${result.platform}`, - new ProcessIntegrationResultQueueMessage(result.id), + await emitter.triggerResultProcessing( + result.tenantId, + result.platform, + result.id, + result.id, + result.onboarding === null ? true : result.onboarding, ) } } diff --git a/services/apps/data_sink_worker/src/bin/restart-x-failed-results.ts b/services/apps/data_sink_worker/src/bin/restart-x-failed-results.ts index f672c08764..1074fea778 100644 --- a/services/apps/data_sink_worker/src/bin/restart-x-failed-results.ts +++ b/services/apps/data_sink_worker/src/bin/restart-x-failed-results.ts @@ -1,11 +1,18 @@ -import { DB_CONFIG, SQS_CONFIG } from '../conf' +import { DB_CONFIG, REDIS_CONFIG, SQS_CONFIG, UNLEASH_CONFIG } from '../conf' import DataSinkRepository from '../repo/dataSink.repo' import { partition } from '@crowd/common' import { DbStore, getDbConnection } from '@crowd/database' import { getServiceTracer } from '@crowd/tracing' import { getServiceLogger } from '@crowd/logging' -import { DataSinkWorkerEmitter, getSqsClient } from '@crowd/sqs' +import { getSqsClient } from '@crowd/sqs' import { ProcessIntegrationResultQueueMessage } from '@crowd/types' +import { + DataSinkWorkerEmitter, + PriorityLevelContextRepository, + QueuePriorityContextLoader, +} from '@crowd/common_services' +import { getUnleashClient } from '@crowd/feature-flags' +import { getRedisClient } from '@crowd/redis' const MAX_TO_PROCESS = 500 @@ -24,13 +31,20 @@ let numResults = parseInt(processArguments[0], 10) numResults = Math.min(numResults, MAX_TO_PROCESS) setImmediate(async () => { - const sqsClient = getSqsClient(SQS_CONFIG()) - const emitter = new DataSinkWorkerEmitter(sqsClient, tracer, log) - await emitter.init() + const unleash = await getUnleashClient(UNLEASH_CONFIG()) + const redis = await getRedisClient(REDIS_CONFIG()) const dbConnection = await getDbConnection(DB_CONFIG()) const store = new DbStore(log, dbConnection) + const priorityLevelRepo = new PriorityLevelContextRepository(store, log) + const loader: QueuePriorityContextLoader = (tenantId: string) => + priorityLevelRepo.loadPriorityLevelContext(tenantId) + + const sqsClient = getSqsClient(SQS_CONFIG()) + const emitter = new DataSinkWorkerEmitter(sqsClient, redis, tracer, unleash, loader, log) + await emitter.init() + const repo = new DataSinkRepository(store, log) const results = await repo.getFailedResults(1, numResults) @@ -44,6 +58,7 @@ setImmediate(async () => { const messages = results.map((r) => { return { + tenantId: r.tenantId, payload: new ProcessIntegrationResultQueueMessage(r.id), groupId: r.id, deduplicationId: r.id, @@ -52,7 +67,7 @@ setImmediate(async () => { const batches = partition(messages, 10) for (const batch of batches) { - await emitter.sendMessages(batch) + await emitter.sendMessagesBatch(batch) } log.info(`Restarted total of ${results.length} failed results.`) diff --git a/services/apps/data_sink_worker/src/conf/index.ts b/services/apps/data_sink_worker/src/conf/index.ts index c993f7559e..45c5af4b43 100644 --- a/services/apps/data_sink_worker/src/conf/index.ts +++ b/services/apps/data_sink_worker/src/conf/index.ts @@ -7,12 +7,14 @@ import { ISqsClientConfig } from '@crowd/sqs' import { ITemporalConfig } from '@crowd/temporal' import config from 'config' import { ISearchSyncApiConfig } from '@crowd/opensearch' +import { QueuePriorityLevel } from '@crowd/types' export interface ISlackAlertingConfig { url: string } export interface IWorkerConfig { maxStreamRetries: number + queuePriorityLevel: QueuePriorityLevel } let workerSettings: IWorkerConfig diff --git a/services/apps/data_sink_worker/src/jobs/processOldResults.ts b/services/apps/data_sink_worker/src/jobs/processOldResults.ts index d5d399edff..065123ed0a 100644 --- a/services/apps/data_sink_worker/src/jobs/processOldResults.ts +++ b/services/apps/data_sink_worker/src/jobs/processOldResults.ts @@ -3,10 +3,14 @@ import { DbConnection, DbStore } from '@crowd/database' import { Unleash } from '@crowd/feature-flags' import { Logger } from '@crowd/logging' import { RedisClient } from '@crowd/redis' -import { NodejsWorkerEmitter, SearchSyncWorkerEmitter, DataSinkWorkerEmitter } from '@crowd/sqs' import { Client as TemporalClient } from '@crowd/temporal' import DataSinkRepository from '../repo/dataSink.repo' import DataSinkService from '../service/dataSink.service' +import { + DataSinkWorkerEmitter, + NodejsWorkerEmitter, + SearchSyncWorkerEmitter, +} from '@crowd/common_services' const MAX_CONCURRENT_PROMISES = 2 const MAX_RESULTS_TO_LOAD = 10 diff --git a/services/apps/data_sink_worker/src/main.ts b/services/apps/data_sink_worker/src/main.ts index a8d3e347ec..21ac0b5bd6 100644 --- a/services/apps/data_sink_worker/src/main.ts +++ b/services/apps/data_sink_worker/src/main.ts @@ -1,12 +1,14 @@ -import { getDbConnection } from '@crowd/database' -import { getServiceTracer } from '@crowd/tracing' -import { getServiceLogger } from '@crowd/logging' import { - NodejsWorkerEmitter, - SearchSyncWorkerEmitter, + PriorityLevelContextRepository, DataSinkWorkerEmitter, - getSqsClient, -} from '@crowd/sqs' + QueuePriorityContextLoader, + SearchSyncWorkerEmitter, + NodejsWorkerEmitter, +} from '@crowd/common_services' +import { DbStore, getDbConnection } from '@crowd/database' +import { getServiceTracer } from '@crowd/tracing' +import { getServiceLogger } from '@crowd/logging' +import { getSqsClient } from '@crowd/sqs' import { DB_CONFIG, SENTIMENT_CONFIG, @@ -14,6 +16,7 @@ import { REDIS_CONFIG, UNLEASH_CONFIG, TEMPORAL_CONFIG, + WORKER_SETTINGS, } from './conf' import { WorkerQueueReceiver } from './queue' import { initializeSentimentAnalysis } from '@crowd/sentiment' @@ -49,13 +52,39 @@ setImmediate(async () => { initializeSentimentAnalysis(SENTIMENT_CONFIG()) } - const nodejsWorkerEmitter = new NodejsWorkerEmitter(sqsClient, tracer, log) + const priorityLevelRepo = new PriorityLevelContextRepository(new DbStore(log, dbConnection), log) + const loader: QueuePriorityContextLoader = (tenantId: string) => + priorityLevelRepo.loadPriorityLevelContext(tenantId) - const searchSyncWorkerEmitter = new SearchSyncWorkerEmitter(sqsClient, tracer, log) + const nodejsWorkerEmitter = new NodejsWorkerEmitter( + sqsClient, + redisClient, + tracer, + unleash, + loader, + log, + ) - const dataWorkerEmitter = new DataSinkWorkerEmitter(sqsClient, tracer, log) + const searchSyncWorkerEmitter = new SearchSyncWorkerEmitter( + sqsClient, + redisClient, + tracer, + unleash, + loader, + log, + ) + + const dataWorkerEmitter = new DataSinkWorkerEmitter( + sqsClient, + redisClient, + tracer, + unleash, + loader, + log, + ) const queue = new WorkerQueueReceiver( + WORKER_SETTINGS().queuePriorityLevel, sqsClient, dbConnection, nodejsWorkerEmitter, diff --git a/services/apps/data_sink_worker/src/queue/index.ts b/services/apps/data_sink_worker/src/queue/index.ts index f7ccade232..d7a9a50f4a 100644 --- a/services/apps/data_sink_worker/src/queue/index.ts +++ b/services/apps/data_sink_worker/src/queue/index.ts @@ -1,27 +1,27 @@ import { Tracer, Span, SpanStatusCode } from '@crowd/tracing' import { Logger } from '@crowd/logging' import { DbConnection, DbStore } from '@crowd/database' -import { - DATA_SINK_WORKER_QUEUE_SETTINGS, - NodejsWorkerEmitter, - SearchSyncWorkerEmitter, - DataSinkWorkerEmitter, - SqsClient, - SqsQueueReceiver, -} from '@crowd/sqs' +import { DATA_SINK_WORKER_QUEUE_SETTINGS, SqsClient, SqsPrioritizedQueueReciever } from '@crowd/sqs' import { CreateAndProcessActivityResultQueueMessage, DataSinkWorkerQueueMessageType, IQueueMessage, ProcessIntegrationResultQueueMessage, + QueuePriorityLevel, } from '@crowd/types' import DataSinkService from '../service/dataSink.service' import { RedisClient } from '@crowd/redis' import { Unleash } from '@crowd/feature-flags' import { Client as TemporalClient } from '@crowd/temporal' +import { + DataSinkWorkerEmitter, + NodejsWorkerEmitter, + SearchSyncWorkerEmitter, +} from '@crowd/common_services' -export class WorkerQueueReceiver extends SqsQueueReceiver { +export class WorkerQueueReceiver extends SqsPrioritizedQueueReciever { constructor( + level: QueuePriorityLevel, client: SqsClient, private readonly dbConn: DbConnection, private readonly nodejsWorkerEmitter: NodejsWorkerEmitter, @@ -34,7 +34,14 @@ export class WorkerQueueReceiver extends SqsQueueReceiver { parentLog: Logger, maxConcurrentProcessing: number, ) { - super(client, DATA_SINK_WORKER_QUEUE_SETTINGS, maxConcurrentProcessing, tracer, parentLog) + super( + level, + client, + DATA_SINK_WORKER_QUEUE_SETTINGS, + maxConcurrentProcessing, + tracer, + parentLog, + ) } override async processMessage(message: IQueueMessage): Promise { diff --git a/services/apps/data_sink_worker/src/repo/activity.data.ts b/services/apps/data_sink_worker/src/repo/activity.data.ts index cd65dee2d5..c4a8ec3d2c 100644 --- a/services/apps/data_sink_worker/src/repo/activity.data.ts +++ b/services/apps/data_sink_worker/src/repo/activity.data.ts @@ -1,5 +1,6 @@ import { DbColumnSet, DbInstance } from '@crowd/database' import { ISentimentAnalysisResult } from '@crowd/sentiment' +import { PlatformType } from '@crowd/types' export interface IDbActivity { id: string @@ -105,6 +106,7 @@ export interface IDbActivityUpdateData { channel?: string url?: string organizationId?: string + platform?: PlatformType } let updateActivityColumnSet: DbColumnSet @@ -132,6 +134,7 @@ export const getUpdateActivityColumnSet = (instance: DbInstance): DbColumnSet => 'url', 'updatedAt', 'organizationId', + 'platform', ], { table: { diff --git a/services/apps/data_sink_worker/src/repo/activity.repo.ts b/services/apps/data_sink_worker/src/repo/activity.repo.ts index 78335c5f36..b6840a1a68 100644 --- a/services/apps/data_sink_worker/src/repo/activity.repo.ts +++ b/services/apps/data_sink_worker/src/repo/activity.repo.ts @@ -1,5 +1,5 @@ import { generateUUIDv1 } from '@crowd/common' -import { DbColumnSet, DbStore, RepositoryBase } from '@crowd/database' +import { DbColumnSet, DbStore, RepositoryBase, eqOrNull } from '@crowd/database' import { Logger } from '@crowd/logging' import { IDbActivity, @@ -47,6 +47,7 @@ export default class ActivityRepository extends RepositoryBase { const result = await this.db().oneOrNone(this.findExistingActivityQuery, { tenantId, @@ -62,11 +64,59 @@ export default class ActivityRepository extends RepositoryBase { + const result = await this.db().oneOrNone( + ` + select id, + type, + platform, + timestamp, + "isContribution", + score, + "sourceId", + "sourceParentId", + "parentId", + "memberId", + username, + "objectMemberId", + "objectMemberUsername", + attributes, + body, + title, + channel, + url, + sentiment, + "deletedAt" + from activities + where "tenantId" = $(tenantId) + and "segmentId" = $(segmentId) + and "sourceId" = $(sourceId) + and channel = $(channel) + and "deletedAt" IS NULL + limit 1; + `, + { + tenantId, + segmentId, + sourceId, + channel, + }, + ) + + return result + } + public async delete(id: string): Promise { await this.db().none('delete from activities where id = $(id)', { id }) } diff --git a/services/apps/data_sink_worker/src/repo/dataSink.data.ts b/services/apps/data_sink_worker/src/repo/dataSink.data.ts index fa5470eee4..8b48dd4db8 100644 --- a/services/apps/data_sink_worker/src/repo/dataSink.data.ts +++ b/services/apps/data_sink_worker/src/repo/dataSink.data.ts @@ -1,4 +1,9 @@ -import { IIntegrationResult, IntegrationResultState, PlatformType } from '@crowd/types' +import { + IIntegrationResult, + IQueuePriorityCalculationContext, + IntegrationResultState, + PlatformType, +} from '@crowd/types' export interface IResultData { id: string @@ -6,6 +11,7 @@ export interface IResultData { data: IIntegrationResult runId: string | null + onboarding: boolean | null webhookId: string | null streamId: string apiDataId: string @@ -22,8 +28,16 @@ export interface IResultData { delayedUntil: string | null } -export interface IFailedResultData { +export interface IFailedResultData extends IQueuePriorityCalculationContext { id: string + onboarding: boolean | null tenantId: string platform: string } + +export interface IDelayedResults { + id: string + tenantId: string + platform: PlatformType + onboarding: boolean | null +} diff --git a/services/apps/data_sink_worker/src/repo/dataSink.repo.ts b/services/apps/data_sink_worker/src/repo/dataSink.repo.ts index 6b4bd13c34..2ef4497473 100644 --- a/services/apps/data_sink_worker/src/repo/dataSink.repo.ts +++ b/services/apps/data_sink_worker/src/repo/dataSink.repo.ts @@ -1,7 +1,8 @@ import { DbStore, RepositoryBase } from '@crowd/database' import { Logger } from '@crowd/logging' -import { IIntegrationResult, IntegrationResultState, PlatformType, TenantPlans } from '@crowd/types' -import { IFailedResultData, IResultData } from './dataSink.data' +import { IIntegrationResult, IntegrationResultState, TenantPlans } from '@crowd/types' +import { IDelayedResults, IFailedResultData, IResultData } from './dataSink.data' +import { distinct, singleOrDefault } from '@crowd/common' export default class DataSinkRepository extends RepositoryBase { constructor(dbStore: DbStore, parentLog: Logger) { @@ -24,10 +25,12 @@ export default class DataSinkRepository extends RepositoryBase { @@ -162,9 +165,14 @@ export default class DataSinkRepository extends RepositoryBase { + public async getDelayedResults(limit: number): Promise { this.ensureTransactional() try { - const results = await this.db().any( + const resultData = await this.db().any( ` - select r.id, r."tenantId", i.platform + select r.id, + r."tenantId", + i.platform, + r."runId" from integration.results r - join integrations i on r."integrationId" = i.id - where r.state = $(delayedState) - and r."delayedUntil" < now() + inner join integrations i on r."integrationId" = i.id + where r.state = $(delayedState) and r."delayedUntil" < now() limit ${limit} for update skip locked; `, @@ -267,7 +280,30 @@ export default class DataSinkRepository extends RepositoryBase ({ id: s.id, tenantId: s.tenantId, platform: s.platform })) + const runIds = distinct(resultData.map((r) => r.runId)) + if (runIds.length > 0) { + const runInfos = await this.db().any( + ` + select id, onboarding + from integration.runs + where id in ($(runIds:csv)) + `, + { + runIds, + }, + ) + + for (const result of resultData) { + const runInfo = singleOrDefault(runInfos, (r) => r.id === result.runId) + if (runInfo) { + result.onboarding = runInfo.onboarding + } else { + result.onboarding = true + } + } + } + + return resultData } catch (err) { this.log.error(err, 'Failed to get delayed results!') throw err diff --git a/services/apps/data_sink_worker/src/repo/organization.data.ts b/services/apps/data_sink_worker/src/repo/organization.data.ts index d209103917..ad274a27f2 100644 --- a/services/apps/data_sink_worker/src/repo/organization.data.ts +++ b/services/apps/data_sink_worker/src/repo/organization.data.ts @@ -49,7 +49,6 @@ export interface IDbInsertOrganizationData { export interface IDbInsertOrganizationCacheData { name: string - displayName?: string url: string | null description: string | null emails: string[] | null @@ -188,9 +187,28 @@ export function getUpdateOrganizationColumnSet(instance: DbInstance): DbColumnSe return updateOrganizationColumnSet } -export interface IDbCacheOrganization extends IDbOrganization { +export interface IDbCacheOrganization { + id: string + names: string[] + url: string | null + description: string | null + emails: string[] | null + logo: string | null + tags: string[] | null + github: IOrganizationSocial | null + twitter: IOrganizationSocial | null + linkedin: IOrganizationSocial | null + crunchbase: IOrganizationSocial | null + employees: number | null + location: string | null + website: string | null + type: string | null + size: string | null + headline: string | null + industry: string | null + founded: string | null + attributes: IAttributes | null enriched: boolean - name: string } let insertCacheOrganizationColumnSet: DbColumnSet @@ -200,7 +218,6 @@ export function getInsertCacheOrganizationColumnSet(instance: DbInstance): DbCol insertCacheOrganizationColumnSet = new instance.helpers.ColumnSet( [ 'id', - 'name', 'url', 'description', 'emails', @@ -212,7 +229,6 @@ export function getInsertCacheOrganizationColumnSet(instance: DbInstance): DbCol 'crunchbase', 'employees', 'location', - 'website', 'type', 'size', 'headline', @@ -239,7 +255,6 @@ export function getUpdateCacheOrganizationColumnSet(instance: DbInstance): DbCol updateCacheOrganizationColumnSet = new instance.helpers.ColumnSet( [ - 'name', 'url', 'description', 'emails', @@ -251,7 +266,6 @@ export function getUpdateCacheOrganizationColumnSet(instance: DbInstance): DbCol 'crunchbase', 'employees', 'location', - 'website', 'type', 'size', 'headline', diff --git a/services/apps/data_sink_worker/src/repo/organization.repo.ts b/services/apps/data_sink_worker/src/repo/organization.repo.ts index dafb5bddab..f7cafd6990 100644 --- a/services/apps/data_sink_worker/src/repo/organization.repo.ts +++ b/services/apps/data_sink_worker/src/repo/organization.repo.ts @@ -1,5 +1,12 @@ +import { generateUUIDv1 } from '@crowd/common' import { DbColumnSet, DbStore, RepositoryBase } from '@crowd/database' import { Logger } from '@crowd/logging' +import { + IOrganization, + IOrganizationIdSource, + IOrganizationIdentity, + SyncStatus, +} from '@crowd/types' import { IDbCacheOrganization, IDbInsertOrganizationCacheData, @@ -9,64 +16,86 @@ import { IDbUpdateOrganizationData, getInsertCacheOrganizationColumnSet, getInsertOrganizationColumnSet, - getUpdateCacheOrganizationColumnSet, - getUpdateOrganizationColumnSet, } from './organization.data' -import { generateUUIDv1 } from '@crowd/common' -import { - IOrganizationIdentity, - SyncStatus, - IOrganization, - IOrganizationIdSource, -} from '@crowd/types' export class OrganizationRepository extends RepositoryBase { private readonly insertCacheOrganizationColumnSet: DbColumnSet - private readonly updateCacheOrganizationColumnSet: DbColumnSet private readonly insertOrganizationColumnSet: DbColumnSet - private readonly updateOrganizationColumnSet: DbColumnSet constructor(dbStore: DbStore, parentLog: Logger) { super(dbStore, parentLog) this.insertCacheOrganizationColumnSet = getInsertCacheOrganizationColumnSet(this.dbInstance) - this.updateCacheOrganizationColumnSet = getUpdateCacheOrganizationColumnSet(this.dbInstance) - this.insertOrganizationColumnSet = getInsertOrganizationColumnSet(this.dbInstance) - this.updateOrganizationColumnSet = getUpdateOrganizationColumnSet(this.dbInstance) + } + + private static findCacheQuery = ` + with identities as ( + select oci.id, + array_agg(oci.name) as names, + max(oci.website) as website + from "organizationCacheIdentities" oci + group by oci.id + ) + select oc.id, + oc.url, + oc.description, + oc.emails, + oc.logo, + oc.tags, + oc.github, + oc.twitter, + oc.linkedin, + oc.crunchbase, + oc.employees, + oc.location, + oc.type, + oc.size, + oc.headline, + oc.industry, + oc.founded, + i.names, + i.website + from "organizationCacheIdentities" oci + inner join "organizationCaches" oc on oci.id = oc.id + inner join identities i on oci.id = i.id + ` + + public async findCacheByWebsite(website: string): Promise { + // limit 1 because multiple rows can have the same website in organizationCacheIdentities + const result = await this.db().oneOrNone( + `${OrganizationRepository.findCacheQuery} where oci.website = $(website) limit 1`, + { website }, + ) + + return result } public async findCacheByName(name: string): Promise { + // limit is not needed since only 1 row can have the same name in organizationCacheIdentities const result = await this.db().oneOrNone( - ` - select id, - name, - url, - description, - emails, - logo, - tags, - github, - twitter, - linkedin, - crunchbase, - employees, - location, - website, - type, - size, - headline, - industry, - founded - from "organizationCaches" - where name = $(name);`, + `${OrganizationRepository.findCacheQuery} where oci.name = $(name)`, { name }, ) return result } + public async linkCacheAndOrganization(cacheId: string, organizationId: string): Promise { + await this.db().none( + ` + insert into "organizationCacheLinks"("organizationCacheId", "organizationId") + values ($(cacheId), $(organizationId)) + on conflict do nothing; + `, + { + cacheId, + organizationId, + }, + ) + } + public async insertCache(data: IDbInsertOrganizationCacheData): Promise { const id = generateUUIDv1() const ts = new Date() @@ -82,14 +111,32 @@ export class OrganizationRepository extends RepositoryBase, + nameToCreateIdentity?: string, ): Promise { - const keys = Object.keys(data) + const keys = Object.keys(data).filter((k) => k !== 'website' && k !== 'name') keys.push('updatedAt') // construct custom column set const dynamicColumnSet = new this.dbInstance.helpers.ColumnSet(keys, { @@ -109,9 +156,38 @@ export class OrganizationRepository extends RepositoryBase): Promise { + // handle manuallyChanged + const result = await this.db().oneOrNone( + `select id, "manuallyChangedFields" from organizations where id = $(id)`, + { + id, + }, + ) + if (!result) { + throw new Error(`Organization with id ${id} not found!`) + } + const manuallyChangedFields = result.manuallyChangedFields || [] + for (const column of manuallyChangedFields) { + if (column in data) { + delete data[column] + } + } + const keys = Object.keys(data) keys.push('updatedAt') // construct dynamic column set @@ -458,6 +551,7 @@ export class OrganizationRepository extends RepositoryBase { try { @@ -91,38 +93,50 @@ export default class ActivityService extends LoggerBase { return id }) - const handle = await this.temporal.workflow.start('processNewActivityAutomation', { - workflowId: `${TemporalWorkflowId.NEW_ACTIVITY_AUTOMATION}/${id}`, - taskQueue: TEMPORAL_CONFIG().automationsTaskQueue, - workflowIdReusePolicy: WorkflowIdReusePolicy.WORKFLOW_ID_REUSE_POLICY_REJECT_DUPLICATE, - retry: { - maximumAttempts: 100, - }, - args: [ - { - tenantId, - activityId: id, + try { + const handle = await this.temporal.workflow.start('processNewActivityAutomation', { + workflowId: `${TemporalWorkflowId.NEW_ACTIVITY_AUTOMATION}/${id}`, + taskQueue: TEMPORAL_CONFIG().automationsTaskQueue, + workflowIdReusePolicy: WorkflowIdReusePolicy.WORKFLOW_ID_REUSE_POLICY_REJECT_DUPLICATE, + retry: { + maximumAttempts: 100, }, - ], - searchAttributes: { - TenantId: [tenantId], - }, - }) - this.log.info( - { workflowId: handle.workflowId }, - 'Started temporal workflow to process new activity automation!', - ) + args: [ + { + tenantId, + activityId: id, + }, + ], + searchAttributes: { + TenantId: [tenantId], + }, + }) + this.log.info( + { workflowId: handle.workflowId }, + 'Started temporal workflow to process new activity automation!', + ) + } catch (err) { + this.log.error( + err, + 'Error while starting temporal workflow to process new activity automation!', + ) + throw err + } const affectedIds = await this.conversationService.processActivity(tenantId, segmentId, id) if (fireSync) { - await this.searchSyncWorkerEmitter.triggerMemberSync(tenantId, activity.memberId) - await this.searchSyncWorkerEmitter.triggerActivitySync(tenantId, id) + await this.searchSyncWorkerEmitter.triggerMemberSync( + tenantId, + activity.memberId, + onboarding, + ) + await this.searchSyncWorkerEmitter.triggerActivitySync(tenantId, id, onboarding) } if (affectedIds.length > 0) { for (const affectedId of affectedIds.filter((i) => i !== id)) { - await this.searchSyncWorkerEmitter.triggerActivitySync(tenantId, affectedId) + await this.searchSyncWorkerEmitter.triggerActivitySync(tenantId, affectedId, onboarding) } } @@ -136,6 +150,7 @@ export default class ActivityService extends LoggerBase { public async update( id: string, tenantId: string, + onboarding: boolean, segmentId: string, activity: IActivityUpdateData, original: IDbActivity, @@ -182,6 +197,7 @@ export default class ActivityService extends LoggerBase { channel: toUpdate.channel || original.channel, url: toUpdate.url || original.url, organizationId: toUpdate.organizationId || original.organizationId, + platform: toUpdate.platform || (original.platform as PlatformType), }) return true @@ -195,8 +211,12 @@ export default class ActivityService extends LoggerBase { await this.conversationService.processActivity(tenantId, segmentId, id) if (fireSync) { - await this.searchSyncWorkerEmitter.triggerMemberSync(tenantId, activity.memberId) - await this.searchSyncWorkerEmitter.triggerActivitySync(tenantId, id) + await this.searchSyncWorkerEmitter.triggerMemberSync( + tenantId, + activity.memberId, + onboarding, + ) + await this.searchSyncWorkerEmitter.triggerActivitySync(tenantId, id, onboarding) } } } catch (err) { @@ -299,6 +319,11 @@ export default class ActivityService extends LoggerBase { organizationId = data.organizationId } + let platform: PlatformType | undefined + if (!arePrimitivesDbEqual(original.platform, data.platform)) { + platform = data.platform + } + return { type, isContribution, @@ -316,12 +341,14 @@ export default class ActivityService extends LoggerBase { channel, url, organizationId, + platform, } } public async processActivity( tenantId: string, integrationId: string, + onboarding: boolean, platform: PlatformType, activity: IActivityData, providedSegmentId?: string, @@ -436,14 +463,41 @@ export default class ActivityService extends LoggerBase { : dbIntegration.segmentId } - // find existing activity - const dbActivity = await txRepo.findExisting( - tenantId, - segmentId, - activity.sourceId, - platform, - activity.type, - ) + let dbActivity: IDbActivity | null + + if ( + (platform === PlatformType.GITHUB && + activity.type === GithubActivityType.AUTHORED_COMMIT) || + platform === PlatformType.GIT + ) { + // we are looking up without platform and type, so we can find the activity with platform = github + // and "enrich" it with git data + // we also include channel here, because different repos (channels) might have the same commit hash + + if (!activity.channel) { + this.log.error('Missing activity channel for github authored commit or git activity!') + throw new Error( + 'Missing activity channel for github authored commit or git activity!', + ) + } + + dbActivity = await txRepo.findExistingBySourceIdAndChannel( + tenantId, + segmentId, + activity.sourceId, + activity.channel, + ) + } else { + // find existing activity + dbActivity = await txRepo.findExisting( + tenantId, + segmentId, + activity.sourceId, + platform, + activity.type, + activity.channel, + ) + } if (dbActivity && dbActivity?.deletedAt) { // we found an existing activity but it's deleted - nothing to do here @@ -481,7 +535,11 @@ export default class ActivityService extends LoggerBase { // delete activity await txRepo.delete(dbActivity.id) - await this.searchSyncWorkerEmitter.triggerRemoveActivity(tenantId, dbActivity.id) + await this.searchSyncWorkerEmitter.triggerRemoveActivity( + tenantId, + dbActivity.id, + onboarding, + ) createActivity = true } @@ -489,6 +547,7 @@ export default class ActivityService extends LoggerBase { await txMemberService.update( dbMember.id, tenantId, + onboarding, segmentId, integrationId, { @@ -527,6 +586,7 @@ export default class ActivityService extends LoggerBase { await txMemberService.update( dbMember.id, tenantId, + onboarding, segmentId, integrationId, { @@ -591,6 +651,7 @@ export default class ActivityService extends LoggerBase { await this.searchSyncWorkerEmitter.triggerRemoveActivity( tenantId, dbActivity.id, + onboarding, ) createActivity = true } @@ -599,6 +660,7 @@ export default class ActivityService extends LoggerBase { await txMemberService.update( dbObjectMember.id, tenantId, + onboarding, segmentId, integrationId, { @@ -637,6 +699,7 @@ export default class ActivityService extends LoggerBase { await txMemberService.update( dbObjectMember.id, tenantId, + onboarding, segmentId, integrationId, { @@ -670,6 +733,7 @@ export default class ActivityService extends LoggerBase { await txActivityService.update( dbActivity.id, tenantId, + onboarding, segmentId, { type: activity.type, @@ -687,6 +751,10 @@ export default class ActivityService extends LoggerBase { channel: activity.channel, url: activity.url, organizationId, + platform: + platform === PlatformType.GITHUB && dbActivity.platform === PlatformType.GIT + ? PlatformType.GITHUB + : (dbActivity.platform as PlatformType), }, dbActivity, false, @@ -708,6 +776,7 @@ export default class ActivityService extends LoggerBase { await txMemberService.update( dbMember.id, tenantId, + onboarding, segmentId, integrationId, { @@ -731,6 +800,7 @@ export default class ActivityService extends LoggerBase { ) memberId = await txMemberService.create( tenantId, + onboarding, segmentId, integrationId, { @@ -767,6 +837,7 @@ export default class ActivityService extends LoggerBase { await txMemberService.update( dbObjectMember.id, tenantId, + onboarding, segmentId, integrationId, { @@ -790,6 +861,7 @@ export default class ActivityService extends LoggerBase { ) objectMemberId = await txMemberService.create( tenantId, + onboarding, segmentId, integrationId, { @@ -839,6 +911,7 @@ export default class ActivityService extends LoggerBase { url: activity.url, organizationId, }, + onboarding, false, ) } @@ -848,13 +921,13 @@ export default class ActivityService extends LoggerBase { }) if (memberId) { - await this.searchSyncWorkerEmitter.triggerMemberSync(tenantId, memberId) + await this.searchSyncWorkerEmitter.triggerMemberSync(tenantId, memberId, onboarding) } if (objectMemberId) { - await this.searchSyncWorkerEmitter.triggerMemberSync(tenantId, objectMemberId) + await this.searchSyncWorkerEmitter.triggerMemberSync(tenantId, objectMemberId, onboarding) } if (activityId) { - await this.searchSyncWorkerEmitter.triggerActivitySync(tenantId, activityId) + await this.searchSyncWorkerEmitter.triggerActivitySync(tenantId, activityId, onboarding) } } catch (err) { this.log.error(err, 'Error while processing an activity!') diff --git a/services/apps/data_sink_worker/src/service/dataSink.service.ts b/services/apps/data_sink_worker/src/service/dataSink.service.ts index c5ed1b4aee..b429217d02 100644 --- a/services/apps/data_sink_worker/src/service/dataSink.service.ts +++ b/services/apps/data_sink_worker/src/service/dataSink.service.ts @@ -1,7 +1,6 @@ import { DbStore } from '@crowd/database' import { Logger, LoggerBase, getChildLogger } from '@crowd/logging' import { RedisClient } from '@crowd/redis' -import { NodejsWorkerEmitter, SearchSyncWorkerEmitter, DataSinkWorkerEmitter } from '@crowd/sqs' import { IActivityData, IMemberData, @@ -19,6 +18,11 @@ import { Client as TemporalClient } from '@crowd/temporal' import { IResultData } from '../repo/dataSink.data' import { addSeconds } from '@crowd/common' import { WORKER_SETTINGS } from '../conf' +import { + DataSinkWorkerEmitter, + NodejsWorkerEmitter, + SearchSyncWorkerEmitter, +} from '@crowd/common_services' import telemetry from '@crowd/telemetry' export default class DataSinkService extends LoggerBase { @@ -81,6 +85,7 @@ export default class DataSinkService extends LoggerBase { result.platform, result.id, result.id, + result.onboarding === null ? true : result.onboarding, `${result.id}-delayed-${Date.now()}`, ) } @@ -165,6 +170,7 @@ export default class DataSinkService extends LoggerBase { await service.processActivity( resultInfo.tenantId, resultInfo.integrationId, + resultInfo.onboarding === null ? true : resultInfo.onboarding, platform, activityData, data.segmentId, diff --git a/services/apps/data_sink_worker/src/service/member.service.ts b/services/apps/data_sink_worker/src/service/member.service.ts index 18c4df8310..dd176871c3 100644 --- a/services/apps/data_sink_worker/src/service/member.service.ts +++ b/services/apps/data_sink_worker/src/service/member.service.ts @@ -19,15 +19,16 @@ import { } from '@crowd/types' import mergeWith from 'lodash.mergewith' import isEqual from 'lodash.isequal' +import moment from 'moment-timezone' import { IMemberCreateData, IMemberUpdateData } from './member.data' import MemberAttributeService from './memberAttribute.service' -import { NodejsWorkerEmitter, SearchSyncWorkerEmitter } from '@crowd/sqs' import IntegrationRepository from '../repo/integration.repo' import { OrganizationService } from './organization.service' import uniqby from 'lodash.uniqby' import { Unleash } from '@crowd/feature-flags' import { TEMPORAL_CONFIG } from '../conf' import { RedisClient } from '@crowd/redis' +import { NodejsWorkerEmitter, SearchSyncWorkerEmitter } from '@crowd/common_services' export default class MemberService extends LoggerBase { constructor( @@ -44,6 +45,7 @@ export default class MemberService extends LoggerBase { public async create( tenantId: string, + onboarding: boolean, segmentId: string, integrationId: string, data: IMemberCreateData, @@ -128,35 +130,44 @@ export default class MemberService extends LoggerBase { } }) - const handle = await this.temporal.workflow.start('processNewMemberAutomation', { - workflowId: `${TemporalWorkflowId.NEW_MEMBER_AUTOMATION}/${id}`, - taskQueue: TEMPORAL_CONFIG().automationsTaskQueue, - workflowIdReusePolicy: WorkflowIdReusePolicy.WORKFLOW_ID_REUSE_POLICY_REJECT_DUPLICATE, - retry: { - maximumAttempts: 100, - }, + try { + const handle = await this.temporal.workflow.start('processNewMemberAutomation', { + workflowId: `${TemporalWorkflowId.NEW_MEMBER_AUTOMATION}/${id}`, + taskQueue: TEMPORAL_CONFIG().automationsTaskQueue, + workflowIdReusePolicy: WorkflowIdReusePolicy.WORKFLOW_ID_REUSE_POLICY_REJECT_DUPLICATE, + retry: { + maximumAttempts: 100, + }, - args: [ - { - tenantId, - memberId: id, + args: [ + { + tenantId, + memberId: id, + }, + ], + searchAttributes: { + TenantId: [tenantId], }, - ], - searchAttributes: { - TenantId: [tenantId], - }, - }) - this.log.info( - { workflowId: handle.workflowId }, - 'Started temporal workflow to process new member automation!', - ) + }) + + this.log.info( + { workflowId: handle.workflowId }, + 'Started temporal workflow to process new member automation!', + ) + } catch (err) { + this.log.error( + err, + 'Error while starting temporal workflow to process new member automation!', + ) + throw err + } if (fireSync) { - await this.searchSyncWorkerEmitter.triggerMemberSync(tenantId, id) + await this.searchSyncWorkerEmitter.triggerMemberSync(tenantId, id, onboarding) } for (const org of organizations) { - await this.searchSyncWorkerEmitter.triggerOrganizationSync(tenantId, org.id) + await this.searchSyncWorkerEmitter.triggerOrganizationSync(tenantId, org.id, onboarding) } return id @@ -169,6 +180,7 @@ export default class MemberService extends LoggerBase { public async update( id: string, tenantId: string, + onboarding: boolean, segmentId: string, integrationId: string, data: IMemberUpdateData, @@ -275,11 +287,11 @@ export default class MemberService extends LoggerBase { }) if (updated && fireSync) { - await this.searchSyncWorkerEmitter.triggerMemberSync(tenantId, id) + await this.searchSyncWorkerEmitter.triggerMemberSync(tenantId, id, onboarding) } for (const org of organizations) { - await this.searchSyncWorkerEmitter.triggerOrganizationSync(tenantId, org.id) + await this.searchSyncWorkerEmitter.triggerOrganizationSync(tenantId, org.id, onboarding) } } catch (err) { this.log.error(err, { memberId: id }, 'Error while updating a member!') @@ -401,6 +413,7 @@ export default class MemberService extends LoggerBase { await txService.update( dbMember.id, tenantId, + false, segmentId, integrationId, { @@ -471,6 +484,7 @@ export default class MemberService extends LoggerBase { await txService.update( dbMember.id, tenantId, + false, segmentId, integrationId, { @@ -542,6 +556,15 @@ export default class MemberService extends LoggerBase { if (member.joinedAt) { const newDate = member.joinedAt const oldDate = new Date(dbMember.joinedAt) + // If either the new or the old date are earlier than 1970 + // it means they come from an activity without timestamp + // and we want to keep the other one + if (moment(oldDate).subtract(5, 'days').unix() < 0) { + joinedAt = newDate.toISOString() + } + if (moment(newDate).unix() < 0) { + joinedAt = undefined + } if (oldDate <= newDate) { // we already have the oldest date in the db, so we don't need to update it diff --git a/services/apps/data_sink_worker/src/service/organization.service.ts b/services/apps/data_sink_worker/src/service/organization.service.ts index ac1d5a4e1c..35db531d01 100644 --- a/services/apps/data_sink_worker/src/service/organization.service.ts +++ b/services/apps/data_sink_worker/src/service/organization.service.ts @@ -1,7 +1,7 @@ import mergeWith from 'lodash.mergewith' import isEqual from 'lodash.isequal' import IntegrationRepository from '../repo/integration.repo' -import { IDbInsertOrganizationCacheData } from '../repo/organization.data' +import { IDbCacheOrganization, IDbInsertOrganizationCacheData } from '../repo/organization.data' import { OrganizationRepository } from '../repo/organization.repo' import { DbStore } from '@crowd/database' import { Logger, LoggerBase, getChildLogger } from '@crowd/logging' @@ -54,8 +54,20 @@ export class OrganizationService extends LoggerBase { this.log.trace(`Checking organization exists in cache..`) - // find from cache by primary identity - let cached = await txRepo.findCacheByName(primaryIdentity.name) + // find from cache by website if we have one + let cached: IDbCacheOrganization | null = null + let createCacheIdentity = false + if (data.website) { + cached = await txRepo.findCacheByWebsite(data.website) + + if (cached && !cached.names.includes(primaryIdentity.name)) { + createCacheIdentity = true + } + } + + if (!cached) { + cached = await txRepo.findCacheByName(primaryIdentity.name) + } if (cached) { this.log.trace({ cached }, `Organization exists in cache!`) @@ -88,7 +100,11 @@ export class OrganizationService extends LoggerBase { } }) if (Object.keys(updateData).length > 0) { - await this.repo.updateCache(cached.id, updateData) + await this.repo.updateCache( + cached.id, + updateData, + createCacheIdentity ? primaryIdentity.name : undefined, + ) cached = { ...cached, ...updateData } // Update the cached data with the new data } } else { @@ -125,7 +141,7 @@ export class OrganizationService extends LoggerBase { enriched: false, ...insertData, attributes: {}, - weakIdentities: data.weakIdentities, + names: [primaryIdentity.name], } } @@ -206,7 +222,7 @@ export class OrganizationService extends LoggerBase { await this.checkForStrongWeakIdentities(txRepo, tenantId, data) const payload = { - displayName: cached.name, + displayName: primaryIdentity.name, description: cached.description, emails: cached.emails, logo: cached.logo, @@ -224,7 +240,7 @@ export class OrganizationService extends LoggerBase { industry: cached.industry, founded: cached.founded, attributes, - weakIdentities: cached.weakIdentities, + weakIdentities: data.weakIdentities, } this.log.trace({ payload }, `Creating new organization!`) @@ -255,6 +271,8 @@ export class OrganizationService extends LoggerBase { } } + await txRepo.linkCacheAndOrganization(cached.id, id) + return id }) diff --git a/services/apps/emails_worker/package.json b/services/apps/emails_worker/package.json index d0638631c6..2f4cd087b9 100644 --- a/services/apps/emails_worker/package.json +++ b/services/apps/emails_worker/package.json @@ -19,7 +19,7 @@ "@crowd/common": "file:../../libs/common", "@crowd/cubejs": "file:../../libs/cubejs", "@crowd/types": "file:../../libs/types", - "@sendgrid/mail": "~7.7.0", + "@sendgrid/mail": "~8.1.0", "@temporalio/activity": "~1.8.6", "@temporalio/client": "~1.8.6", "@temporalio/workflow": "~1.8.6", diff --git a/services/apps/emails_worker/src/activities/weekly-analytics/buildEmailFromDatabase.ts b/services/apps/emails_worker/src/activities/weekly-analytics/buildEmailFromDatabase.ts index c76344783e..d29f588921 100644 --- a/services/apps/emails_worker/src/activities/weekly-analytics/buildEmailFromDatabase.ts +++ b/services/apps/emails_worker/src/activities/weekly-analytics/buildEmailFromDatabase.ts @@ -10,7 +10,7 @@ import { PlatformType, SegmentRawData, } from '@crowd/types' -import { ActivityDisplayService } from '@crowd/integrations' +import { ActivityDisplayService, DEFAULT_ACTIVITY_TYPE_SETTINGS } from '@crowd/integrations' import { svc } from '../../main' @@ -195,7 +195,10 @@ export async function getTopActivityTypes( platform: a.platform, type: a.type, }, - input.segments.reduce((acc, s) => lodash.merge(acc, s.customActivityTypes), {}), + { + default: DEFAULT_ACTIVITY_TYPE_SETTINGS, + custom: input.segments.reduce((acc, s) => lodash.merge(acc, s.customActivityTypes), {}), + }, [ActivityDisplayVariant.SHORT], ) const prettyName: string = displayOptions.short @@ -278,7 +281,13 @@ export async function getConversations(input: InputAnalyticsWithSegments): Promi const displayOptions = ActivityDisplayService.getDisplayOptions( conversationStarterActivity, - input.segments.reduce((acc, s) => lodash.merge(acc, s.customActivityTypes), {}), + { + default: DEFAULT_ACTIVITY_TYPE_SETTINGS, + custom: input.segments.reduce( + (acc, s) => lodash.merge(acc, s.customActivityTypes), + {}, + ), + }, [ActivityDisplayVariant.SHORT], ) diff --git a/services/apps/emails_worker/src/activities/weekly-analytics/getNextEmails.ts b/services/apps/emails_worker/src/activities/weekly-analytics/getNextEmails.ts index 36603288ed..9f55db901b 100644 --- a/services/apps/emails_worker/src/activities/weekly-analytics/getNextEmails.ts +++ b/services/apps/emails_worker/src/activities/weekly-analytics/getNextEmails.ts @@ -35,7 +35,10 @@ export async function weeklyGetNextEmails(): Promise { try { rows = await svc.postgres.reader.connection().query(` SELECT id as "tenantId", name as "tenantName" - FROM tenants WHERE "deletedAt" IS NULL; + FROM tenants + WHERE "deletedAt" IS NULL + AND plan IN ('Scale', 'Growth', 'Essential') + AND ("trialEndsAt" > NOW() OR "trialEndsAt" IS NULL); `) } catch (err) { throw new Error(err) diff --git a/services/apps/emails_worker/src/main.ts b/services/apps/emails_worker/src/main.ts index ffb433ff5a..25456e171d 100644 --- a/services/apps/emails_worker/src/main.ts +++ b/services/apps/emails_worker/src/main.ts @@ -38,6 +38,9 @@ const options: Options = { postgres: { enabled: true, }, + opensearch: { + enabled: false, + }, } export const svc = new ServiceWorker(config, options) diff --git a/services/apps/emails_worker/src/workflows/weekly-analytics/sendEmailAndUpdateHistory.ts b/services/apps/emails_worker/src/workflows/weekly-analytics/sendEmailAndUpdateHistory.ts index a5d44ab754..801574c0e4 100644 --- a/services/apps/emails_worker/src/workflows/weekly-analytics/sendEmailAndUpdateHistory.ts +++ b/services/apps/emails_worker/src/workflows/weekly-analytics/sendEmailAndUpdateHistory.ts @@ -24,7 +24,7 @@ const { getTotalActivitiesPreviousWeek, getNewActivitiesThisWeek, getNewActivitiesPreviousWeek, -} = proxyActivities({ startToCloseTimeout: '15 seconds' }) +} = proxyActivities({ startToCloseTimeout: '5 minutes' }) // Configure timeouts and retry policies to fetch content from the database. const { @@ -36,7 +36,7 @@ const { getTopActivityTypes, getConversations, getActiveTenantIntegrations, -} = proxyActivities({ startToCloseTimeout: '10 seconds' }) +} = proxyActivities({ startToCloseTimeout: '20 seconds' }) // Configure timeouts and retry policies to actually send the email. const { weeklySendEmail } = proxyActivities({ diff --git a/services/apps/entity_merging_worker/.eslintrc.cjs b/services/apps/entity_merging_worker/.eslintrc.cjs new file mode 100644 index 0000000000..25ba4e0d66 --- /dev/null +++ b/services/apps/entity_merging_worker/.eslintrc.cjs @@ -0,0 +1,21 @@ +module.exports = { + parser: '@typescript-eslint/parser', + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:prettier/recommended', + ], + plugins: ['@typescript-eslint', 'prettier'], + parserOptions: { + ecmaVersion: 2022, + sourceType: 'module', + }, + env: { + es6: true, + node: true, + }, + rules: { + 'prettier/prettier': 'error', + '@typescript-eslint/explicit-module-boundary-types': 'off', + }, +} diff --git a/services/apps/entity_merging_worker/.prettierignore b/services/apps/entity_merging_worker/.prettierignore new file mode 100644 index 0000000000..2b24877309 --- /dev/null +++ b/services/apps/entity_merging_worker/.prettierignore @@ -0,0 +1,3 @@ +dist/ +.eslintrc.cjs +.prettierrc.cjs diff --git a/services/apps/entity_merging_worker/.prettierrc.cjs b/services/apps/entity_merging_worker/.prettierrc.cjs new file mode 100644 index 0000000000..a8ca459839 --- /dev/null +++ b/services/apps/entity_merging_worker/.prettierrc.cjs @@ -0,0 +1,7 @@ +module.exports = { + singleQuote: true, + arrowParens: 'always', + printWidth: 100, + trailingComma: 'all', + semi: false, +} diff --git a/services/apps/entity_merging_worker/package.json b/services/apps/entity_merging_worker/package.json new file mode 100644 index 0000000000..248656ae72 --- /dev/null +++ b/services/apps/entity_merging_worker/package.json @@ -0,0 +1,48 @@ +{ + "name": "@crowd/entity-merging-worker", + "version": "1.0.0", + "private": true, + "scripts": { + "start": "CROWD_TEMPORAL_TASKQUEUE=entity-merging SERVICE=entity-merging-worker TS_NODE_TRANSPILE_ONLY=true node -r tsconfig-paths/register -r ts-node/register src/main.ts", + "start:debug:local": "set -a && . ../../../backend/.env.dist.local && . ../../../backend/.env.override.local && set +a && CROWD_TEMPORAL_TASKQUEUE=entity-merging SERVICE=entity-merging-worker TS_NODE_TRANSPILE_ONLY=true LOG_LEVEL=trace node --inspect=0.0.0.0:9232 -r tsconfig-paths/register -r ts-node/register src/main.ts", + "start:debug": "CROWD_TEMPORAL_TASKQUEUE=entity-merging SERVICE=entity-merging-worker TS_NODE_TRANSPILE_ONLY=true LOG_LEVEL=trace node --inspect=0.0.0.0:9232 -r tsconfig-paths/register -r ts-node/register src/main.ts", + "dev:local": "./node_modules/.bin/nodemon --watch src --watch ../../libs --ext ts --exec npm run start:debug:local", + "dev": "./node_modules/.bin/nodemon --watch src --watch ../../libs --ext ts --exec npm run start:debug", + "lint": "./node_modules/.bin/eslint --ext .ts src --max-warnings=0", + "format": "./node_modules/.bin/prettier --write \"src/**/*.ts\"", + "format-check": "./node_modules/.bin/prettier --check .", + "tsc-check": "./node_modules/.bin/tsc --noEmit" + }, + "dependencies": { + "@crowd/archetype-standard": "file:../../archetypes/standard", + "@crowd/archetype-worker": "file:../../archetypes/worker", + "@crowd/common": "file:../../libs/common", + "@crowd/feature-flags": "file:../../libs/feature-flags", + "@crowd/types": "file:../../libs/types", + "@crowd/redis": "file:../../libs/redis", + "@sendgrid/mail": "~8.1.0", + "@temporalio/activity": "~1.8.6", + "@temporalio/client": "~1.8.6", + "@temporalio/workflow": "~1.8.6", + "axios": "~1.5.1", + "html-to-text": "~9.0.5", + "lodash": "~4.17.21", + "moment": "~2.29.4", + "moment-timezone": "^0.5.34", + "ts-node": "^10.9.1", + "tsconfig-paths": "^4.2.0", + "typescript": "^5.2.2", + "uuid": "~9.0.1" + }, + "devDependencies": { + "@types/node": "^20.8.2", + "@types/uuid": "~9.0.6", + "@typescript-eslint/eslint-plugin": "^6.7.4", + "@typescript-eslint/parser": "^6.7.4", + "eslint": "^8.50.0", + "eslint-config-prettier": "^9.0.0", + "eslint-plugin-prettier": "^5.0.0", + "nodemon": "^3.0.1", + "prettier": "^3.0.3" + } +} diff --git a/services/apps/entity_merging_worker/src/activities.ts b/services/apps/entity_merging_worker/src/activities.ts new file mode 100644 index 0000000000..bf5f3764ed --- /dev/null +++ b/services/apps/entity_merging_worker/src/activities.ts @@ -0,0 +1,8 @@ +export { deleteMember, moveActivitiesBetweenMembers } from './activities/members' + +export { + deleteOrganization, + moveActivitiesBetweenOrgs, + markMergeActionDone, + notifyFrontend, +} from './activities/organizations' diff --git a/services/apps/entity_merging_worker/src/activities/members.ts b/services/apps/entity_merging_worker/src/activities/members.ts new file mode 100644 index 0000000000..816881c87e --- /dev/null +++ b/services/apps/entity_merging_worker/src/activities/members.ts @@ -0,0 +1,48 @@ +import { svc } from '../main' + +export async function deleteMember(memberId: string): Promise { + await svc.postgres.writer.connection().query( + ` + DELETE FROM "memberSegments" + WHERE "memberId" = $1 + `, + [memberId], + ) + await svc.postgres.writer.connection().query( + ` + DELETE FROM members + WHERE id = $1 + `, + [memberId], + ) +} + +export async function moveActivitiesBetweenMembers( + primaryId: string, + secondaryId: string, + tenantId: string, +): Promise { + const memberExists = await svc.postgres.writer.connection().oneOrNone( + ` + SELECT id + FROM members + WHERE id = $1 + AND "tenantId" = $2 + `, + [primaryId, tenantId], + ) + + if (!memberExists) { + return + } + + await svc.postgres.writer.connection().query( + ` + UPDATE activities + SET "memberId" = $1 + WHERE "memberId" = $2 + AND "tenantId" = $3; + `, + [primaryId, secondaryId, tenantId], + ) +} diff --git a/services/apps/entity_merging_worker/src/activities/organizations.ts b/services/apps/entity_merging_worker/src/activities/organizations.ts new file mode 100644 index 0000000000..5c3a1fbed1 --- /dev/null +++ b/services/apps/entity_merging_worker/src/activities/organizations.ts @@ -0,0 +1,105 @@ +import { RedisPubSubEmitter } from '@crowd/redis' +import { svc } from '../main' +import { ApiWebsocketMessage } from '@crowd/types' + +export async function deleteOrganization(organizationId: string): Promise { + await svc.postgres.writer.connection().query( + ` + DELETE FROM "organizationCacheLinks" + WHERE "organizationId" = $1 + `, + [organizationId], + ) + await svc.postgres.writer.connection().query( + ` + DELETE FROM "organizationSegments" + WHERE "organizationId" = $1 + `, + [organizationId], + ) + await svc.postgres.writer.connection().query( + ` + DELETE FROM organizations + WHERE id = $1 + `, + [organizationId], + ) +} + +export async function moveActivitiesBetweenOrgs( + primaryId: string, + secondaryId: string, + tenantId: string, +): Promise { + const result = await svc.postgres.writer.connection().result( + ` + UPDATE "activities" + SET "organizationId" = $1 + WHERE id IN ( + SELECT id + FROM "activities" + WHERE "tenantId" = $3 + AND "organizationId" = $2 + LIMIT 5000 + ) + `, + [primaryId, secondaryId, tenantId], + ) + + return result.rowCount > 0 +} + +export async function markMergeActionDone( + primaryId: string, + secondaryId: string, + tenantId: string, +): Promise { + await svc.postgres.writer.connection().query( + ` + UPDATE "mergeActions" + SET state = $4 + WHERE "tenantId" = $3 + AND type = $5 + AND "primaryId" = $1 + AND "secondaryId" = $2 + AND state != $4 + `, + [primaryId, secondaryId, tenantId, 'done', 'org'], + ) +} + +export async function notifyFrontend( + primaryOrgId: string, + secondaryOrgId: string, + original: string, + toMerge: string, + tenantId: string, + userId: string, +): Promise { + const emitter = new RedisPubSubEmitter( + 'api-pubsub', + svc.redis, + (err) => { + svc.log.error({ err }, 'Error in api-ws emitter!') + }, + svc.log, + ) + + emitter.emit( + 'user', + new ApiWebsocketMessage( + 'org-merge', + JSON.stringify({ + success: true, + tenantId, + userId, + primaryOrgId, + secondaryOrgId, + original, + toMerge, + }), + undefined, + tenantId, + ), + ) +} diff --git a/services/apps/entity_merging_worker/src/main.ts b/services/apps/entity_merging_worker/src/main.ts new file mode 100644 index 0000000000..840b025af4 --- /dev/null +++ b/services/apps/entity_merging_worker/src/main.ts @@ -0,0 +1,31 @@ +import { Config } from '@crowd/archetype-standard' +import { ServiceWorker, Options } from '@crowd/archetype-worker' + +const config: Config = { + envvars: [], + producer: { + enabled: false, + }, + temporal: { + enabled: true, + }, + redis: { + enabled: true, + }, +} + +const options: Options = { + postgres: { + enabled: true, + }, + opensearch: { + enabled: false, + }, +} + +export const svc = new ServiceWorker(config, options) + +setImmediate(async () => { + await svc.init() + await svc.start() +}) diff --git a/services/apps/entity_merging_worker/src/workflows.ts b/services/apps/entity_merging_worker/src/workflows.ts new file mode 100644 index 0000000000..6610559158 --- /dev/null +++ b/services/apps/entity_merging_worker/src/workflows.ts @@ -0,0 +1 @@ +export { finishMemberMerging, finishOrganizationMerging } from './workflows/all' diff --git a/services/apps/entity_merging_worker/src/workflows/all.ts b/services/apps/entity_merging_worker/src/workflows/all.ts new file mode 100644 index 0000000000..7cf848850f --- /dev/null +++ b/services/apps/entity_merging_worker/src/workflows/all.ts @@ -0,0 +1,41 @@ +import { proxyActivities } from '@temporalio/workflow' + +import * as activities from '../activities' + +const { + deleteMember, + moveActivitiesBetweenMembers, + deleteOrganization, + moveActivitiesBetweenOrgs, + markMergeActionDone, + notifyFrontend, +} = proxyActivities({ + startToCloseTimeout: '10 seconds', +}) + +export async function finishMemberMerging( + primaryId: string, + secondaryId: string, + tenantId: string, +): Promise { + await moveActivitiesBetweenMembers(primaryId, secondaryId, tenantId) + await deleteMember(secondaryId) +} + +export async function finishOrganizationMerging( + primaryId: string, + secondaryId: string, + original: string, + toMerge: string, + tenantId: string, + userId: string, +): Promise { + let movedSomething = true + do { + movedSomething = await moveActivitiesBetweenOrgs(primaryId, secondaryId, tenantId) + } while (movedSomething) + + await deleteOrganization(secondaryId) + await markMergeActionDone(primaryId, secondaryId, tenantId) + await notifyFrontend(primaryId, secondaryId, original, toMerge, tenantId, userId) +} diff --git a/services/apps/entity_merging_worker/tsconfig.json b/services/apps/entity_merging_worker/tsconfig.json new file mode 100644 index 0000000000..472d00201e --- /dev/null +++ b/services/apps/entity_merging_worker/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "es2017", + "module": "commonjs", + "declaration": true, + "outDir": "./dist", + "lib": ["es6", "es7", "es2017", "es2017.object", "es2015.promise", "ES2017.String"], + "skipLibCheck": true, + "moduleResolution": "node", + "sourceMap": true, + "experimentalDecorators": true, + "esModuleInterop": true, + "baseUrl": "./src", + "paths": { + "@crowd/*": ["../../../libs/*/src"], + "@crowd/archetype-*": ["../../../archetypes/*/src"] + } + }, + "include": ["src/**/*"] +} diff --git a/services/apps/integration_data_worker/config/custom-environment-variables.json b/services/apps/integration_data_worker/config/custom-environment-variables.json index f1c35bbb41..68fc776a23 100644 --- a/services/apps/integration_data_worker/config/custom-environment-variables.json +++ b/services/apps/integration_data_worker/config/custom-environment-variables.json @@ -19,6 +19,10 @@ "host": "CROWD_REDIS_HOST", "port": "CROWD_REDIS_PORT" }, + "unleash": { + "url": "CROWD_UNLEASH_URL", + "apiKey": "CROWD_UNLEASH_BACKEND_API_KEY" + }, "slackAlerting": { "url": "CROWD_SLACK_ALERTING_URL" }, @@ -30,5 +34,8 @@ "privateKey": "CROWD_GITHUB_PRIVATE_KEY", "webhookSecret": "CROWD_GITHUB_WEBHOOK_SECRET", "isCommitDataEnabled": "CROWD_GITHUB_IS_COMMIT_DATA_ENABLED" + }, + "worker": { + "queuePriorityLevel": "QUEUE_PRIORITY_LEVEL" } } diff --git a/services/apps/integration_data_worker/config/default.json b/services/apps/integration_data_worker/config/default.json index 96f8915d70..3c3201bd30 100644 --- a/services/apps/integration_data_worker/config/default.json +++ b/services/apps/integration_data_worker/config/default.json @@ -2,7 +2,9 @@ "db": {}, "sqs": {}, "redis": {}, + "unleash": {}, "worker": { - "maxDataRetries": 5 + "maxDataRetries": 5, + "queuePriorityLevel": "normal" } } diff --git a/services/apps/integration_data_worker/package.json b/services/apps/integration_data_worker/package.json index 50ab2d2d56..53718adaae 100644 --- a/services/apps/integration_data_worker/package.json +++ b/services/apps/integration_data_worker/package.json @@ -25,6 +25,8 @@ "@crowd/tracing": "file:../../libs/tracing", "@crowd/types": "file:../../libs/types", "@crowd/alerting": "file:../../libs/alerting", + "@crowd/feature-flags": "file:../../libs/feature-flags", + "@crowd/common_services": "file:../../libs/common_services", "@crowd/telemetry": "file:../../libs/telemetry", "@types/config": "^3.3.0", "@types/node": "^18.16.3", diff --git a/services/apps/integration_data_worker/src/bin/process-data-for-tenant.ts b/services/apps/integration_data_worker/src/bin/process-data-for-tenant.ts index b746e0613e..3ed3c12a1a 100644 --- a/services/apps/integration_data_worker/src/bin/process-data-for-tenant.ts +++ b/services/apps/integration_data_worker/src/bin/process-data-for-tenant.ts @@ -1,10 +1,17 @@ -import { DB_CONFIG, SQS_CONFIG } from '../conf' +import { DB_CONFIG, REDIS_CONFIG, SQS_CONFIG, UNLEASH_CONFIG } from '../conf' import IntegrationDataRepository from '../repo/integrationData.repo' import { DbStore, getDbConnection } from '@crowd/database' import { getServiceTracer } from '@crowd/tracing' import { getServiceLogger } from '@crowd/logging' -import { IntegrationDataWorkerEmitter, getSqsClient } from '@crowd/sqs' +import { getSqsClient } from '@crowd/sqs' import { IntegrationStreamDataState } from '@crowd/types' +import { getUnleashClient } from '@crowd/feature-flags' +import { getRedisClient } from '@crowd/redis' +import { + IntegrationDataWorkerEmitter, + PriorityLevelContextRepository, + QueuePriorityContextLoader, +} from '@crowd/common_services' const tracer = getServiceTracer() const log = getServiceLogger() @@ -19,12 +26,25 @@ if (processArguments.length !== 1) { const tenantId = processArguments[0] setImmediate(async () => { + const unleash = await getUnleashClient(UNLEASH_CONFIG()) + const dbConnection = await getDbConnection(DB_CONFIG()) + const store = new DbStore(log, dbConnection) + const redisClient = await getRedisClient(REDIS_CONFIG(), true) + const priorityLevelRepo = new PriorityLevelContextRepository(store, log) + const loader: QueuePriorityContextLoader = (tenantId: string) => + priorityLevelRepo.loadPriorityLevelContext(tenantId) + const sqsClient = getSqsClient(SQS_CONFIG()) - const emitter = new IntegrationDataWorkerEmitter(sqsClient, tracer, log) + const emitter = new IntegrationDataWorkerEmitter( + sqsClient, + redisClient, + tracer, + unleash, + loader, + log, + ) await emitter.init() - const dbConnection = await getDbConnection(DB_CONFIG()) - const store = new DbStore(log, dbConnection) const repo = new IntegrationDataRepository(store, log) const dataIds = await repo.getDataForTenant(tenantId) @@ -37,7 +57,12 @@ setImmediate(async () => { await repo.resetStream(dataId) } - await emitter.triggerDataProcessing(info.tenantId, info.integrationType, dataId) + await emitter.triggerDataProcessing( + info.tenantId, + info.integrationType, + dataId, + info.onboarding === null ? true : info.onboarding, + ) } else { log.error({ dataId }, 'Data stream not found!') process.exit(1) diff --git a/services/apps/integration_data_worker/src/bin/process-data.ts b/services/apps/integration_data_worker/src/bin/process-data.ts index 6c9203b4e4..aeaacd6c25 100644 --- a/services/apps/integration_data_worker/src/bin/process-data.ts +++ b/services/apps/integration_data_worker/src/bin/process-data.ts @@ -1,10 +1,17 @@ -import { DB_CONFIG, SQS_CONFIG } from '../conf' +import { DB_CONFIG, REDIS_CONFIG, SQS_CONFIG, UNLEASH_CONFIG } from '../conf' import IntegrationDataRepository from '../repo/integrationData.repo' import { DbStore, getDbConnection } from '@crowd/database' import { getServiceTracer } from '@crowd/tracing' import { getServiceLogger } from '@crowd/logging' -import { IntegrationDataWorkerEmitter, getSqsClient } from '@crowd/sqs' +import { getSqsClient } from '@crowd/sqs' import { IntegrationStreamDataState } from '@crowd/types' +import { getUnleashClient } from '@crowd/feature-flags' +import { getRedisClient } from '@crowd/redis' +import { + IntegrationDataWorkerEmitter, + PriorityLevelContextRepository, + QueuePriorityContextLoader, +} from '@crowd/common_services' const tracer = getServiceTracer() const log = getServiceLogger() @@ -19,12 +26,25 @@ if (processArguments.length !== 1) { const dataIds = processArguments[0].split(',') setImmediate(async () => { + const unleash = await getUnleashClient(UNLEASH_CONFIG()) + const dbConnection = await getDbConnection(DB_CONFIG()) + const store = new DbStore(log, dbConnection) + const redisClient = await getRedisClient(REDIS_CONFIG(), true) + const priorityLevelRepo = new PriorityLevelContextRepository(store, log) + const loader: QueuePriorityContextLoader = (tenantId: string) => + priorityLevelRepo.loadPriorityLevelContext(tenantId) + const sqsClient = getSqsClient(SQS_CONFIG()) - const emitter = new IntegrationDataWorkerEmitter(sqsClient, tracer, log) + const emitter = new IntegrationDataWorkerEmitter( + sqsClient, + redisClient, + tracer, + unleash, + loader, + log, + ) await emitter.init() - const dbConnection = await getDbConnection(DB_CONFIG()) - const store = new DbStore(log, dbConnection) const repo = new IntegrationDataRepository(store, log) for (const dataId of dataIds) { @@ -35,7 +55,12 @@ setImmediate(async () => { await repo.resetStream(dataId) } - await emitter.triggerDataProcessing(info.tenantId, info.integrationType, dataId) + await emitter.triggerDataProcessing( + info.tenantId, + info.integrationType, + dataId, + info.onboarding === null ? true : info.onboarding, + ) } else { log.error({ dataId }, 'Data stream not found!') process.exit(1) diff --git a/services/apps/integration_data_worker/src/conf/index.ts b/services/apps/integration_data_worker/src/conf/index.ts index a62fcfcdc4..772ab230ed 100644 --- a/services/apps/integration_data_worker/src/conf/index.ts +++ b/services/apps/integration_data_worker/src/conf/index.ts @@ -1,10 +1,14 @@ +import { IUnleashConfig } from '@crowd/feature-flags' import { IDatabaseConfig } from '@crowd/database' import { IRedisConfiguration } from '@crowd/redis' import { ISqsClientConfig } from '@crowd/sqs' +import { QueuePriorityLevel } from '@crowd/types' import config from 'config' +import { SERVICE } from '@crowd/common' export interface IWorkerSettings { maxDataRetries: number + queuePriorityLevel: QueuePriorityLevel } export interface ISlackAlertingConfig { @@ -72,3 +76,12 @@ export const PLATFORM_CONFIG = (platform: string): unknown | undefined => { return undefined } } + +let unleashConfig: IUnleashConfig | undefined +export const UNLEASH_CONFIG = (): IUnleashConfig | undefined => { + if (unleashConfig) return unleashConfig + + unleashConfig = Object.assign({ appName: SERVICE }, config.get('unleash')) + + return unleashConfig +} diff --git a/services/apps/integration_data_worker/src/jobs/processOldData.ts b/services/apps/integration_data_worker/src/jobs/processOldData.ts index e76791fb1d..e4d4a9ce6f 100644 --- a/services/apps/integration_data_worker/src/jobs/processOldData.ts +++ b/services/apps/integration_data_worker/src/jobs/processOldData.ts @@ -1,9 +1,9 @@ import { DbConnection, DbStore } from '@crowd/database' import { Logger } from '@crowd/logging' import { RedisClient } from '@crowd/redis' -import { DataSinkWorkerEmitter, IntegrationStreamWorkerEmitter } from '@crowd/sqs' import IntegrationDataRepository from '../repo/integrationData.repo' import IntegrationDataService from '../service/integrationDataService' +import { DataSinkWorkerEmitter, IntegrationStreamWorkerEmitter } from '@crowd/common_services' export const processOldDataJob = async ( dbConn: DbConnection, diff --git a/services/apps/integration_data_worker/src/main.ts b/services/apps/integration_data_worker/src/main.ts index 48caa97003..4ee20fcd98 100644 --- a/services/apps/integration_data_worker/src/main.ts +++ b/services/apps/integration_data_worker/src/main.ts @@ -1,11 +1,18 @@ import { getServiceTracer } from '@crowd/tracing' import { getServiceLogger } from '@crowd/logging' -import { DB_CONFIG, REDIS_CONFIG, SQS_CONFIG } from './conf' +import { DB_CONFIG, REDIS_CONFIG, SQS_CONFIG, UNLEASH_CONFIG, WORKER_SETTINGS } from './conf' import { getRedisClient } from '@crowd/redis' -import { getDbConnection } from '@crowd/database' -import { DataSinkWorkerEmitter, IntegrationStreamWorkerEmitter, getSqsClient } from '@crowd/sqs' +import { DbStore, getDbConnection } from '@crowd/database' +import { getSqsClient } from '@crowd/sqs' import { WorkerQueueReceiver } from './queue' import { processOldDataJob } from './jobs/processOldData' +import { + IntegrationStreamWorkerEmitter, + DataSinkWorkerEmitter, + PriorityLevelContextRepository, + QueuePriorityContextLoader, +} from '@crowd/common_services' +import { getUnleashClient } from '@crowd/feature-flags' const tracer = getServiceTracer() const log = getServiceLogger() @@ -16,15 +23,36 @@ const PROCESSING_INTERVAL_MINUTES = 5 setImmediate(async () => { log.info('Starting integration data worker...') + const unleash = await getUnleashClient(UNLEASH_CONFIG()) + const sqsClient = getSqsClient(SQS_CONFIG()) const dbConnection = await getDbConnection(DB_CONFIG(), MAX_CONCURRENT_PROCESSING) const redisClient = await getRedisClient(REDIS_CONFIG(), true) - const streamWorkerEmitter = new IntegrationStreamWorkerEmitter(sqsClient, tracer, log) - const dataSinkWorkerEmitter = new DataSinkWorkerEmitter(sqsClient, tracer, log) + const priorityLevelRepo = new PriorityLevelContextRepository(new DbStore(log, dbConnection), log) + const loader: QueuePriorityContextLoader = (tenantId: string) => + priorityLevelRepo.loadPriorityLevelContext(tenantId) + + const streamWorkerEmitter = new IntegrationStreamWorkerEmitter( + sqsClient, + redisClient, + tracer, + unleash, + loader, + log, + ) + const dataSinkWorkerEmitter = new DataSinkWorkerEmitter( + sqsClient, + redisClient, + tracer, + unleash, + loader, + log, + ) const queue = new WorkerQueueReceiver( + WORKER_SETTINGS().queuePriorityLevel, sqsClient, redisClient, dbConnection, diff --git a/services/apps/integration_data_worker/src/queue/index.ts b/services/apps/integration_data_worker/src/queue/index.ts index 084e6eea04..db9430fcb9 100644 --- a/services/apps/integration_data_worker/src/queue/index.ts +++ b/services/apps/integration_data_worker/src/queue/index.ts @@ -1,23 +1,24 @@ -import { Tracer, Span, SpanStatusCode } from '@crowd/tracing' -import { Logger } from '@crowd/logging' import { DbConnection, DbStore } from '@crowd/database' +import { Logger } from '@crowd/logging' import { RedisClient } from '@crowd/redis' import { INTEGRATION_DATA_WORKER_QUEUE_SETTINGS, - IntegrationStreamWorkerEmitter, - DataSinkWorkerEmitter, SqsClient, - SqsQueueReceiver, + SqsPrioritizedQueueReciever, } from '@crowd/sqs' +import { Span, SpanStatusCode, Tracer } from '@crowd/tracing' import { IQueueMessage, IntegrationDataWorkerQueueMessageType, ProcessStreamDataQueueMessage, + QueuePriorityLevel, } from '@crowd/types' import IntegrationStreamService from '../service/integrationDataService' +import { DataSinkWorkerEmitter, IntegrationStreamWorkerEmitter } from '@crowd/common_services' -export class WorkerQueueReceiver extends SqsQueueReceiver { +export class WorkerQueueReceiver extends SqsPrioritizedQueueReciever { constructor( + level: QueuePriorityLevel, client: SqsClient, private readonly redisClient: RedisClient, private readonly dbConn: DbConnection, @@ -28,6 +29,7 @@ export class WorkerQueueReceiver extends SqsQueueReceiver { maxConcurrentProcessing: number, ) { super( + level, client, INTEGRATION_DATA_WORKER_QUEUE_SETTINGS, maxConcurrentProcessing, diff --git a/services/apps/integration_data_worker/src/service/integrationDataService.ts b/services/apps/integration_data_worker/src/service/integrationDataService.ts index b7df7fc36e..0ae00eb0aa 100644 --- a/services/apps/integration_data_worker/src/service/integrationDataService.ts +++ b/services/apps/integration_data_worker/src/service/integrationDataService.ts @@ -1,13 +1,13 @@ +import { addSeconds, singleOrDefault } from '@crowd/common' +import { DataSinkWorkerEmitter, IntegrationStreamWorkerEmitter } from '@crowd/common_services' import { DbStore } from '@crowd/database' +import { INTEGRATION_SERVICES, IProcessDataContext } from '@crowd/integrations' import { Logger, LoggerBase, getChildLogger } from '@crowd/logging' import { RedisCache, RedisClient } from '@crowd/redis' -import IntegrationDataRepository from '../repo/integrationData.repo' -import { IActivityData, IntegrationResultType, IntegrationRunState } from '@crowd/types' -import { addSeconds, singleOrDefault } from '@crowd/common' -import { INTEGRATION_SERVICES, IProcessDataContext } from '@crowd/integrations' -import { WORKER_SETTINGS, PLATFORM_CONFIG } from '../conf' -import { DataSinkWorkerEmitter, IntegrationStreamWorkerEmitter } from '@crowd/sqs' import telemetry from '@crowd/telemetry' +import { IActivityData, IntegrationResultType, IntegrationRunState } from '@crowd/types' +import { PLATFORM_CONFIG, WORKER_SETTINGS } from '../conf' +import IntegrationDataRepository from '../repo/integrationData.repo' export default class IntegrationDataService extends LoggerBase { private readonly repo: IntegrationDataRepository @@ -136,11 +136,24 @@ export default class IntegrationDataService extends LoggerBase { cache, publishActivity: async (activity) => { - await this.publishActivity(dataInfo.tenantId, dataInfo.integrationType, dataId, activity) + await this.publishActivity( + dataInfo.tenantId, + dataInfo.integrationType, + dataId, + dataInfo.onboarding === null ? true : dataInfo.onboarding, + activity, + ) }, publishCustom: async (entity, type) => { - await this.publishCustom(dataInfo.tenantId, dataInfo.integrationType, dataId, type, entity) + await this.publishCustom( + dataInfo.tenantId, + dataInfo.integrationType, + dataId, + dataInfo.onboarding === null ? true : dataInfo.onboarding, + type, + entity, + ) }, publishStream: async (identifier, data) => { @@ -149,6 +162,7 @@ export default class IntegrationDataService extends LoggerBase { dataInfo.integrationType, dataInfo.streamId, identifier, + dataInfo.onboarding === null ? true : dataInfo.onboarding, data, dataInfo.runId, dataInfo.webhookId, @@ -244,6 +258,7 @@ export default class IntegrationDataService extends LoggerBase { tenantId: string, platform: string, dataId: string, + onboarding: boolean, type: IntegrationResultType, entity: unknown, ): Promise { @@ -259,6 +274,7 @@ export default class IntegrationDataService extends LoggerBase { platform, resultId, resultId, + onboarding, ) } catch (err) { await this.triggerDataError( @@ -276,6 +292,7 @@ export default class IntegrationDataService extends LoggerBase { tenantId: string, platform: string, dataId: string, + onboarding: boolean, activity: IActivityData, ): Promise { try { @@ -289,6 +306,7 @@ export default class IntegrationDataService extends LoggerBase { platform, resultId, activity.sourceId, + onboarding, ) } catch (err) { await this.triggerDataError( @@ -355,6 +373,7 @@ export default class IntegrationDataService extends LoggerBase { platform: string, parentId: string, identifier: string, + onboarding: boolean, data?: unknown, runId?: string, webhookId?: string, @@ -368,7 +387,12 @@ export default class IntegrationDataService extends LoggerBase { const streamId = await this.repo.publishStream(parentId, identifier, data, runId, webhookId) if (streamId) { if (runId) { - await this.streamWorkerEmitter.triggerStreamProcessing(tenantId, platform, streamId) + await this.streamWorkerEmitter.triggerStreamProcessing( + tenantId, + platform, + streamId, + onboarding, + ) } else if (webhookId) { await this.streamWorkerEmitter.triggerWebhookProcessing(tenantId, platform, webhookId) } else { diff --git a/services/apps/integration_run_worker/config/custom-environment-variables.json b/services/apps/integration_run_worker/config/custom-environment-variables.json index ebf11a2efa..e676c6ffd2 100644 --- a/services/apps/integration_run_worker/config/custom-environment-variables.json +++ b/services/apps/integration_run_worker/config/custom-environment-variables.json @@ -19,6 +19,10 @@ "host": "CROWD_REDIS_HOST", "port": "CROWD_REDIS_PORT" }, + "unleash": { + "url": "CROWD_UNLEASH_URL", + "apiKey": "CROWD_UNLEASH_BACKEND_API_KEY" + }, "nango": { "url": "CROWD_NANGO_URL", "secretKey": "CROWD_NANGO_SECRET_KEY" @@ -42,5 +46,8 @@ "clientId": "CROWD_TWITTER_CLIENT_ID", "clientSecret": "CROWD_TWITTER_CLIENT_SECRET", "callbackUrl": "CROWD_TWITTER_CALLBACK_URL" + }, + "worker": { + "queuePriorityLevel": "QUEUE_PRIORITY_LEVEL" } } diff --git a/services/apps/integration_run_worker/config/default.json b/services/apps/integration_run_worker/config/default.json index a966bbe509..df904b3681 100644 --- a/services/apps/integration_run_worker/config/default.json +++ b/services/apps/integration_run_worker/config/default.json @@ -2,8 +2,10 @@ "db": {}, "sqs": {}, "redis": {}, + "unleash": {}, "nango": {}, "worker": { - "maxRetries": 5 + "maxRetries": 5, + "queuePriorityLevel": "normal" } } diff --git a/services/apps/integration_run_worker/package.json b/services/apps/integration_run_worker/package.json index a8a47cfe0a..a1c4d4aef1 100644 --- a/services/apps/integration_run_worker/package.json +++ b/services/apps/integration_run_worker/package.json @@ -27,6 +27,8 @@ "@crowd/sqs": "file:../../libs/sqs", "@crowd/tracing": "file:../../libs/tracing", "@crowd/types": "file:../../libs/types", + "@crowd/common_services": "file:../../libs/common_services", + "@crowd/feature-flags": "file:../../libs/feature-flags", "@types/config": "^3.3.0", "@types/node": "^18.16.3", "config": "^3.3.9", diff --git a/services/apps/integration_run_worker/src/bin/continue-run.ts b/services/apps/integration_run_worker/src/bin/continue-run.ts index 13038c4ed3..2aa0a8dc17 100644 --- a/services/apps/integration_run_worker/src/bin/continue-run.ts +++ b/services/apps/integration_run_worker/src/bin/continue-run.ts @@ -1,10 +1,17 @@ -import { DB_CONFIG, SQS_CONFIG } from '../conf' +import { DB_CONFIG, REDIS_CONFIG, SQS_CONFIG, UNLEASH_CONFIG } from '../conf' import { DbStore, getDbConnection } from '@crowd/database' import { getServiceTracer } from '@crowd/tracing' import { getServiceLogger } from '@crowd/logging' -import { IntegrationStreamWorkerEmitter, getSqsClient } from '@crowd/sqs' +import { getSqsClient } from '@crowd/sqs' import IntegrationRunRepository from '../repo/integrationRun.repo' import { IntegrationRunState } from '@crowd/types' +import { + IntegrationStreamWorkerEmitter, + PriorityLevelContextRepository, + QueuePriorityContextLoader, +} from '@crowd/common_services' +import { getUnleashClient } from '@crowd/feature-flags' +import { getRedisClient } from '@crowd/redis' const tracer = getServiceTracer() const log = getServiceLogger() @@ -14,13 +21,20 @@ const processArguments = process.argv.slice(2) const runId = processArguments[0] setImmediate(async () => { - const sqsClient = getSqsClient(SQS_CONFIG()) - const emitter = new IntegrationStreamWorkerEmitter(sqsClient, tracer, log) - await emitter.init() + const unleash = await getUnleashClient(UNLEASH_CONFIG()) + const redis = await getRedisClient(REDIS_CONFIG()) const dbConnection = await getDbConnection(DB_CONFIG()) const store = new DbStore(log, dbConnection) + const priorityLevelRepo = new PriorityLevelContextRepository(store, log) + const loader: QueuePriorityContextLoader = (tenantId: string) => + priorityLevelRepo.loadPriorityLevelContext(tenantId) + + const sqsClient = getSqsClient(SQS_CONFIG()) + const emitter = new IntegrationStreamWorkerEmitter(sqsClient, redis, tracer, unleash, loader, log) + await emitter.init() + const repo = new IntegrationRunRepository(store, log) const run = await repo.findIntegrationRunById(runId) @@ -36,7 +50,7 @@ setImmediate(async () => { log.info(`Triggering integration run for ${runId}!`) - await emitter.continueProcessingRunStreams(run.tenantId, run.platform, run.id) + await emitter.continueProcessingRunStreams(run.tenantId, run.onboarding, run.platform, run.id) process.exit(0) } else { log.error({ run }, 'Run not found!') diff --git a/services/apps/integration_run_worker/src/bin/onboard-integration.ts b/services/apps/integration_run_worker/src/bin/onboard-integration.ts index 30d096e5f4..70157ffabe 100644 --- a/services/apps/integration_run_worker/src/bin/onboard-integration.ts +++ b/services/apps/integration_run_worker/src/bin/onboard-integration.ts @@ -1,10 +1,17 @@ -import { DB_CONFIG, SQS_CONFIG } from '../conf' +import { DB_CONFIG, REDIS_CONFIG, SQS_CONFIG, UNLEASH_CONFIG } from '../conf' import { DbStore, getDbConnection } from '@crowd/database' import { getServiceTracer } from '@crowd/tracing' import { getServiceLogger } from '@crowd/logging' -import { IntegrationRunWorkerEmitter, getSqsClient } from '@crowd/sqs' +import { getSqsClient } from '@crowd/sqs' import IntegrationRunRepository from '../repo/integrationRun.repo' import { IntegrationState } from '@crowd/types' +import { + IntegrationRunWorkerEmitter, + PriorityLevelContextRepository, + QueuePriorityContextLoader, +} from '@crowd/common_services' +import { getUnleashClient } from '@crowd/feature-flags' +import { getRedisClient } from '@crowd/redis' const tracer = getServiceTracer() const log = getServiceLogger() @@ -15,13 +22,19 @@ const parameter = processArguments[0] const isOnboarding = processArguments[1] ? processArguments[1] === 'true' : true setImmediate(async () => { - const sqsClient = getSqsClient(SQS_CONFIG()) - const emitter = new IntegrationRunWorkerEmitter(sqsClient, tracer, log) - await emitter.init() - const dbConnection = await getDbConnection(DB_CONFIG()) const store = new DbStore(log, dbConnection) + const unleash = await getUnleashClient(UNLEASH_CONFIG()) + const redis = await getRedisClient(REDIS_CONFIG()) + const priorityLevelRepo = new PriorityLevelContextRepository(store, log) + const loader: QueuePriorityContextLoader = (tenantId: string) => + priorityLevelRepo.loadPriorityLevelContext(tenantId) + + const sqsClient = getSqsClient(SQS_CONFIG()) + const emitter = new IntegrationRunWorkerEmitter(sqsClient, redis, tracer, unleash, loader, log) + await emitter.init() + const repo = new IntegrationRunRepository(store, log) const integrationIds = parameter.split(',') diff --git a/services/apps/integration_run_worker/src/bin/process-repo.ts b/services/apps/integration_run_worker/src/bin/process-repo.ts index 81adbaa04c..1ef7662cc1 100644 --- a/services/apps/integration_run_worker/src/bin/process-repo.ts +++ b/services/apps/integration_run_worker/src/bin/process-repo.ts @@ -1,8 +1,8 @@ -import { DB_CONFIG, SQS_CONFIG } from '../conf' +import { DB_CONFIG, REDIS_CONFIG, SQS_CONFIG, UNLEASH_CONFIG } from '../conf' import { DbStore, getDbConnection } from '@crowd/database' import { getServiceTracer } from '@crowd/tracing' import { getServiceLogger } from '@crowd/logging' -import { IntegrationRunWorkerEmitter, getSqsClient } from '@crowd/sqs' +import { getSqsClient } from '@crowd/sqs' import IntegrationRunRepository from '../repo/integrationRun.repo' import { IntegrationState } from '@crowd/types' import { @@ -10,6 +10,13 @@ import { GithubManualIntegrationSettings, GithubManualStreamType, } from '@crowd/integrations' +import { + IntegrationRunWorkerEmitter, + PriorityLevelContextRepository, + QueuePriorityContextLoader, +} from '@crowd/common_services' +import { getUnleashClient } from '@crowd/feature-flags' +import { getRedisClient } from '@crowd/redis' const mapStreamTypeToEnum = (stream: string): GithubManualStreamType => { switch (stream) { @@ -34,13 +41,16 @@ const mapStreamTypeToEnum = (stream: string): GithubManualStreamType => { // example call // pnpm run script:process-repo 5f8b1a3a-0b0a-4c0a-8b0a-4c0a8b0a4c0a CrowdDotDev/crowd.dev stars +// example call for all repos +// pnpm run script:process-repo 5f8b1a3a-0b0a-4c0a-8b0a-4c0a8b0a4c0a all forks -- this will trigger forks streams for all repos in settings + const tracer = getServiceTracer() const log = getServiceLogger() const processArguments = process.argv.slice(2) const integrationId = processArguments[0] -const repoFullName = processArguments[1] // it should be in format of owner/repo +const repoFullNames = processArguments[1] ? processArguments[1].split(',') : [] // it should be in format of owner/repo // this is optional, if not provided we will trigger all streams // if provided we will trigger only this stream type @@ -48,16 +58,14 @@ const repoFullName = processArguments[1] // it should be in format of owner/repo const streamString = processArguments.length > 2 ? processArguments[2] : null const streamType = streamString ? mapStreamTypeToEnum(streamString) : GithubManualStreamType.ALL -const repoURL = `https://github.com/${repoFullName}` - setImmediate(async () => { if (!integrationId) { log.error(`Integration id is required!`) process.exit(1) } - if (!repoFullName) { - log.error(`Repo full name is required!`) + if (!repoFullNames.length) { + log.error(`At least one repo full name is required!`) process.exit(1) } @@ -66,12 +74,18 @@ setImmediate(async () => { process.exit(1) } - const sqsClient = getSqsClient(SQS_CONFIG()) - const emitter = new IntegrationRunWorkerEmitter(sqsClient, tracer, log) - await emitter.init() - const dbConnection = await getDbConnection(DB_CONFIG()) const store = new DbStore(log, dbConnection) + const unleash = await getUnleashClient(UNLEASH_CONFIG()) + const redis = await getRedisClient(REDIS_CONFIG()) + + const priorityLevelRepo = new PriorityLevelContextRepository(store, log) + const loader: QueuePriorityContextLoader = (tenantId: string) => + priorityLevelRepo.loadPriorityLevelContext(tenantId) + + const sqsClient = getSqsClient(SQS_CONFIG()) + const emitter = new IntegrationRunWorkerEmitter(sqsClient, redis, tracer, unleash, loader, log) + await emitter.init() const repo = new IntegrationRunRepository(store, log) @@ -100,16 +114,28 @@ setImmediate(async () => { integrationId, )) as GithubIntegrationSettings - // let's check if requested repo exists in current settings - const repoExists = currentSettings.repos.find((r) => r.url === repoURL) + let repos = [] + if (repoFullNames[0] === 'all' && currentSettings.repos) { + repos = currentSettings.repos + } else { + for (const repoFullName of repoFullNames) { + const repoURL = `https://github.com/${repoFullName}` + const repoExists = currentSettings.repos.find((r) => r.url === repoURL) + if (!repoExists) { + log.error(`Repo ${repoURL} is not configured in integration settings, skipping!`) + continue + } + repos.push(repoExists) + } + } - if (!repoExists) { - log.error(`Repo ${repoURL} is not configured in integration settings, skiping!`) + if (!repos.length) { + log.error(`No valid repos found, exiting!`) process.exit(1) } const settings: GithubManualIntegrationSettings = { - repos: [repoExists], + repos, unavailableRepos: [], streamType, } diff --git a/services/apps/integration_run_worker/src/bin/trigger-all-onboardings.ts b/services/apps/integration_run_worker/src/bin/trigger-all-onboardings.ts index 920339f326..c04478f08d 100644 --- a/services/apps/integration_run_worker/src/bin/trigger-all-onboardings.ts +++ b/services/apps/integration_run_worker/src/bin/trigger-all-onboardings.ts @@ -1,22 +1,34 @@ -import { DB_CONFIG, SQS_CONFIG } from '../conf' +import { DB_CONFIG, REDIS_CONFIG, SQS_CONFIG, UNLEASH_CONFIG } from '../conf' import IntegrationRunRepository from '../repo/integrationRun.repo' import { singleOrDefault, timeout } from '@crowd/common' import { DbStore, getDbConnection } from '@crowd/database' import { INTEGRATION_SERVICES } from '@crowd/integrations' import { getServiceTracer } from '@crowd/tracing' import { getServiceLogger } from '@crowd/logging' -import { IntegrationRunWorkerEmitter, getSqsClient } from '@crowd/sqs' +import { getSqsClient } from '@crowd/sqs' +import { + IntegrationRunWorkerEmitter, + PriorityLevelContextRepository, + QueuePriorityContextLoader, +} from '@crowd/common_services' +import { getUnleashClient } from '@crowd/feature-flags' +import { getRedisClient } from '@crowd/redis' const tracer = getServiceTracer() const log = getServiceLogger() setImmediate(async () => { - const sqsClient = getSqsClient(SQS_CONFIG()) - const emitter = new IntegrationRunWorkerEmitter(sqsClient, tracer, log) - await emitter.init() - const dbConnection = await getDbConnection(DB_CONFIG()) const store = new DbStore(log, dbConnection) + const unleash = await getUnleashClient(UNLEASH_CONFIG()) + const redis = await getRedisClient(REDIS_CONFIG()) + const priorityLevelRepo = new PriorityLevelContextRepository(store, log) + const loader: QueuePriorityContextLoader = (tenantId: string) => + priorityLevelRepo.loadPriorityLevelContext(tenantId) + + const sqsClient = getSqsClient(SQS_CONFIG()) + const emitter = new IntegrationRunWorkerEmitter(sqsClient, redis, tracer, unleash, loader, log) + await emitter.init() const repo = new IntegrationRunRepository(store, log) diff --git a/services/apps/integration_run_worker/src/bin/trigger-stream-processed.ts b/services/apps/integration_run_worker/src/bin/trigger-stream-processed.ts index 90e4fea52a..f7b5c4342a 100644 --- a/services/apps/integration_run_worker/src/bin/trigger-stream-processed.ts +++ b/services/apps/integration_run_worker/src/bin/trigger-stream-processed.ts @@ -1,8 +1,15 @@ -import { SQS_CONFIG } from '../conf' -import { getServiceTracer } from '@crowd/tracing' +import { + IntegrationRunWorkerEmitter, + PriorityLevelContextRepository, + QueuePriorityContextLoader, +} from '@crowd/common_services' +import { DbStore, getDbConnection } from '@crowd/database' +import { getUnleashClient } from '@crowd/feature-flags' import { getServiceLogger } from '@crowd/logging' -import { IntegrationRunWorkerEmitter, getSqsClient } from '@crowd/sqs' -import { StreamProcessedQueueMessage } from '@crowd/types' +import { getRedisClient } from '@crowd/redis' +import { getSqsClient } from '@crowd/sqs' +import { getServiceTracer } from '@crowd/tracing' +import { DB_CONFIG, REDIS_CONFIG, SQS_CONFIG, UNLEASH_CONFIG } from '../conf' const tracer = getServiceTracer() const log = getServiceLogger() @@ -10,18 +17,37 @@ const log = getServiceLogger() const processArguments = process.argv.slice(2) if (processArguments.length !== 1) { - log.error('Expected 1 argument: streamIds') + log.error('Expected 1 argument: runIds') process.exit(1) } const runIds = processArguments[0].split(',') setImmediate(async () => { + const unleash = await getUnleashClient(UNLEASH_CONFIG()) + const redis = await getRedisClient(REDIS_CONFIG()) + + const dbConnection = await getDbConnection(DB_CONFIG()) + const store = new DbStore(log, dbConnection) + const priorityLevelRepo = new PriorityLevelContextRepository(store, log) + const loader: QueuePriorityContextLoader = (tenantId: string) => + priorityLevelRepo.loadPriorityLevelContext(tenantId) + const sqsClient = getSqsClient(SQS_CONFIG()) - const emitter = new IntegrationRunWorkerEmitter(sqsClient, tracer, log) + const emitter = new IntegrationRunWorkerEmitter(sqsClient, redis, tracer, unleash, loader, log) await emitter.init() - for (const runId of runIds) { - await emitter.sendMessage(runId, new StreamProcessedQueueMessage(runId)) + const results = await dbConnection.any( + `select r.id, r."tenantId", r.onboarding, i.platform from integration.runs r + inner join integrations i on i.id = r."integrationId" + where r.id in ($runIds:csv)`, + { + runIds, + }, + ) + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + for (const res of results as any[]) { + await emitter.streamProcessed(res.tenantId, res.platform, res.id, res.onboarding) } }) diff --git a/services/apps/integration_run_worker/src/conf/index.ts b/services/apps/integration_run_worker/src/conf/index.ts index 3f8f6819c2..325f17a650 100644 --- a/services/apps/integration_run_worker/src/conf/index.ts +++ b/services/apps/integration_run_worker/src/conf/index.ts @@ -1,7 +1,10 @@ +import { SERVICE } from '@crowd/common' import { IDatabaseConfig } from '@crowd/database' +import { IUnleashConfig } from '@crowd/feature-flags' import { ISearchSyncApiConfig } from '@crowd/opensearch' import { IRedisConfiguration } from '@crowd/redis' import { ISqsClientConfig } from '@crowd/sqs' +import { QueuePriorityLevel } from '@crowd/types' import config from 'config' export interface INangoConfig { @@ -39,6 +42,7 @@ export const REDIS_CONFIG = (): IRedisConfiguration => { export interface IWorkerConfig { maxRetries: number + queuePriorityLevel: QueuePriorityLevel } let workerConfig: IWorkerConfig @@ -90,3 +94,12 @@ export const PLATFORM_CONFIG = (platform: string): unknown | undefined => { export const SEARCH_SYNC_API_CONFIG = (): ISearchSyncApiConfig => { return config.get('searchSyncApi') } + +let unleashConfig: IUnleashConfig | undefined +export const UNLEASH_CONFIG = (): IUnleashConfig | undefined => { + if (unleashConfig) return unleashConfig + + unleashConfig = Object.assign({ appName: SERVICE }, config.get('unleash')) + + return unleashConfig +} diff --git a/services/apps/integration_run_worker/src/main.ts b/services/apps/integration_run_worker/src/main.ts index 0862ed2c3c..13ad0b76c5 100644 --- a/services/apps/integration_run_worker/src/main.ts +++ b/services/apps/integration_run_worker/src/main.ts @@ -1,16 +1,19 @@ -import { getDbConnection } from '@crowd/database' +import { DbStore, getDbConnection } from '@crowd/database' import { getServiceTracer } from '@crowd/tracing' import { getServiceLogger } from '@crowd/logging' +import { getSqsClient } from '@crowd/sqs' +import { DB_CONFIG, REDIS_CONFIG, SQS_CONFIG, UNLEASH_CONFIG, WORKER_CONFIG } from './conf' +import { WorkerQueueReceiver } from './queue' +import { ApiPubSubEmitter, getRedisClient } from '@crowd/redis' import { IntegrationRunWorkerEmitter, IntegrationStreamWorkerEmitter, IntegrationSyncWorkerEmitter, + PriorityLevelContextRepository, + QueuePriorityContextLoader, SearchSyncWorkerEmitter, - getSqsClient, -} from '@crowd/sqs' -import { DB_CONFIG, REDIS_CONFIG, SQS_CONFIG } from './conf' -import { WorkerQueueReceiver } from './queue' -import { ApiPubSubEmitter, getRedisClient } from '@crowd/redis' +} from '@crowd/common_services' +import { getUnleashClient } from '@crowd/feature-flags' const tracer = getServiceTracer() const log = getServiceLogger() @@ -19,22 +22,56 @@ const MAX_CONCURRENT_PROCESSING = 2 setImmediate(async () => { log.info('Starting integration run worker...') + const unleash = await getUnleashClient(UNLEASH_CONFIG()) const sqsClient = getSqsClient(SQS_CONFIG()) const dbConnection = await getDbConnection(DB_CONFIG(), MAX_CONCURRENT_PROCESSING) - const redisClient = await getRedisClient(REDIS_CONFIG(), true) + const redis = await getRedisClient(REDIS_CONFIG(), true) + + const priorityLevelRepo = new PriorityLevelContextRepository(new DbStore(log, dbConnection), log) + const loader: QueuePriorityContextLoader = (tenantId: string) => + priorityLevelRepo.loadPriorityLevelContext(tenantId) - const runWorkerEmitter = new IntegrationRunWorkerEmitter(sqsClient, tracer, log) - const streamWorkerEmitter = new IntegrationStreamWorkerEmitter(sqsClient, tracer, log) - const searchSyncWorkerEmitter = new SearchSyncWorkerEmitter(sqsClient, tracer, log) - const integrationSyncWorkerEmitter = new IntegrationSyncWorkerEmitter(sqsClient, tracer, log) + const runWorkerEmitter = new IntegrationRunWorkerEmitter( + sqsClient, + redis, + tracer, + unleash, + loader, + log, + ) + const streamWorkerEmitter = new IntegrationStreamWorkerEmitter( + sqsClient, + redis, + tracer, + unleash, + loader, + log, + ) + const searchSyncWorkerEmitter = new SearchSyncWorkerEmitter( + sqsClient, + redis, + tracer, + unleash, + loader, + log, + ) + const integrationSyncWorkerEmitter = new IntegrationSyncWorkerEmitter( + sqsClient, + redis, + tracer, + unleash, + loader, + log, + ) - const apiPubSubEmitter = new ApiPubSubEmitter(redisClient, log) + const apiPubSubEmitter = new ApiPubSubEmitter(redis, log) const queue = new WorkerQueueReceiver( + WORKER_CONFIG().queuePriorityLevel, sqsClient, - redisClient, + redis, dbConnection, streamWorkerEmitter, runWorkerEmitter, diff --git a/services/apps/integration_run_worker/src/queue/index.ts b/services/apps/integration_run_worker/src/queue/index.ts index 15ccb34da0..e56ddec416 100644 --- a/services/apps/integration_run_worker/src/queue/index.ts +++ b/services/apps/integration_run_worker/src/queue/index.ts @@ -1,20 +1,23 @@ -import { Tracer, Span, SpanStatusCode } from '@crowd/tracing' -import { Logger } from '@crowd/logging' -import { DbConnection, DbStore } from '@crowd/database' -import { ApiPubSubEmitter, RedisClient } from '@crowd/redis' import { - INTEGRATION_RUN_WORKER_QUEUE_SETTINGS, IntegrationRunWorkerEmitter, IntegrationStreamWorkerEmitter, - SearchSyncWorkerEmitter, IntegrationSyncWorkerEmitter, + SearchSyncWorkerEmitter, +} from '@crowd/common_services' +import { DbConnection, DbStore } from '@crowd/database' +import { Logger } from '@crowd/logging' +import { ApiPubSubEmitter, RedisClient } from '@crowd/redis' +import { + INTEGRATION_RUN_WORKER_QUEUE_SETTINGS, SqsClient, - SqsQueueReceiver, + SqsPrioritizedQueueReciever, } from '@crowd/sqs' +import { Span, SpanStatusCode, Tracer } from '@crowd/tracing' import { GenerateRunStreamsQueueMessage, IQueueMessage, IntegrationRunWorkerQueueMessageType, + QueuePriorityLevel, StartIntegrationRunQueueMessage, StreamProcessedQueueMessage, } from '@crowd/types' @@ -22,8 +25,9 @@ import IntegrationRunService from '../service/integrationRunService' /* eslint-disable no-case-declarations */ -export class WorkerQueueReceiver extends SqsQueueReceiver { +export class WorkerQueueReceiver extends SqsPrioritizedQueueReciever { constructor( + level: QueuePriorityLevel, client: SqsClient, private readonly redisClient: RedisClient, private readonly dbConn: DbConnection, @@ -36,7 +40,14 @@ export class WorkerQueueReceiver extends SqsQueueReceiver { parentLog: Logger, maxConcurrentProcessing: number, ) { - super(client, INTEGRATION_RUN_WORKER_QUEUE_SETTINGS, maxConcurrentProcessing, tracer, parentLog) + super( + level, + client, + INTEGRATION_RUN_WORKER_QUEUE_SETTINGS, + maxConcurrentProcessing, + tracer, + parentLog, + ) } override async processMessage(message: IQueueMessage): Promise { diff --git a/services/apps/integration_run_worker/src/repo/integrationRun.data.ts b/services/apps/integration_run_worker/src/repo/integrationRun.data.ts index 482d5cfdec..f3c67eccc3 100644 --- a/services/apps/integration_run_worker/src/repo/integrationRun.data.ts +++ b/services/apps/integration_run_worker/src/repo/integrationRun.data.ts @@ -29,6 +29,7 @@ export interface IStartIntegrationRunData { export interface IPendingDelayedRun { id: string + onboarding: boolean tenantId: string integrationType: string } diff --git a/services/apps/integration_run_worker/src/repo/integrationRun.repo.ts b/services/apps/integration_run_worker/src/repo/integrationRun.repo.ts index f2e1f83625..e21f50f94e 100644 --- a/services/apps/integration_run_worker/src/repo/integrationRun.repo.ts +++ b/services/apps/integration_run_worker/src/repo/integrationRun.repo.ts @@ -18,7 +18,8 @@ export default class IntegrationRunRepository extends RepositoryBase { const result = await this.db().oneOrNone( ` - select r.id, r.state, r."tenantId", r."integrationId", i.platform + select r.id, r.state, r."tenantId", r."integrationId", i.platform, r.onboarding from integration.runs r inner join integrations i on r."integrationId" = i.id where r.id = $(runId) diff --git a/services/apps/integration_run_worker/src/service/integrationRunService.ts b/services/apps/integration_run_worker/src/service/integrationRunService.ts index 247c5fc061..5710b2bddc 100644 --- a/services/apps/integration_run_worker/src/service/integrationRunService.ts +++ b/services/apps/integration_run_worker/src/service/integrationRunService.ts @@ -7,18 +7,18 @@ import { } from '@crowd/integrations' import { Logger, LoggerBase, getChildLogger } from '@crowd/logging' import { ApiPubSubEmitter, RedisCache, RedisClient } from '@crowd/redis' -import { - IntegrationRunWorkerEmitter, - IntegrationStreamWorkerEmitter, - SearchSyncWorkerEmitter, - IntegrationSyncWorkerEmitter, -} from '@crowd/sqs' import { IntegrationRunState, IntegrationStreamState } from '@crowd/types' import { NANGO_CONFIG, PLATFORM_CONFIG } from '../conf' import IntegrationRunRepository from '../repo/integrationRun.repo' import MemberAttributeSettingsRepository from '../repo/memberAttributeSettings.repo' import SampleDataRepository from '../repo/sampleData.repo' import { AutomationRepository } from '../repo/automation.repo' +import { + IntegrationRunWorkerEmitter, + IntegrationStreamWorkerEmitter, + IntegrationSyncWorkerEmitter, + SearchSyncWorkerEmitter, +} from '@crowd/common_services' export default class IntegrationRunService extends LoggerBase { private readonly repo: IntegrationRunRepository @@ -211,6 +211,7 @@ export default class IntegrationRunService extends LoggerBase { await this.repo.resetDelayedRun(run.id) await this.streamWorkerEmitter.continueProcessingRunStreams( run.tenantId, + run.onboarding, run.integrationType, run.id, ) @@ -270,6 +271,7 @@ export default class IntegrationRunService extends LoggerBase { integrationInfo.tenantId, integrationInfo.type, runId, + onboarding, isManualRun, manualSettings, ) @@ -422,7 +424,14 @@ export default class IntegrationRunService extends LoggerBase { }, publishStream: async (identifier: string, data?: unknown) => { - await this.publishStream(runInfo.tenantId, runInfo.integrationType, runId, identifier, data) + await this.publishStream( + runInfo.tenantId, + runInfo.integrationType, + runId, + identifier, + runInfo.onboarding, + data, + ) }, updateIntegrationSettings: async (settings: unknown) => { @@ -516,12 +525,18 @@ export default class IntegrationRunService extends LoggerBase { platform: string, runId: string, identifier: string, + onboarding: boolean, data?: unknown, ): Promise { try { this.log.debug('Publishing new root stream!') const streamId = await this.repo.publishStream(runId, identifier, data) - await this.streamWorkerEmitter.triggerStreamProcessing(tenantId, platform, streamId) + await this.streamWorkerEmitter.triggerStreamProcessing( + tenantId, + platform, + streamId, + onboarding, + ) } catch (err) { await this.triggerRunError( runId, diff --git a/services/apps/integration_stream_worker/config/custom-environment-variables.json b/services/apps/integration_stream_worker/config/custom-environment-variables.json index c40b0196f3..2e569c5c65 100644 --- a/services/apps/integration_stream_worker/config/custom-environment-variables.json +++ b/services/apps/integration_stream_worker/config/custom-environment-variables.json @@ -19,6 +19,10 @@ "host": "CROWD_REDIS_HOST", "port": "CROWD_REDIS_PORT" }, + "unleash": { + "url": "CROWD_UNLEASH_URL", + "apiKey": "CROWD_UNLEASH_BACKEND_API_KEY" + }, "nango": { "url": "CROWD_NANGO_URL", "secretKey": "CROWD_NANGO_SECRET_KEY" @@ -47,5 +51,8 @@ "clientId": "CROWD_TWITTER_CLIENT_ID", "clientSecret": "CROWD_TWITTER_CLIENT_SECRET", "callbackUrl": "CROWD_TWITTER_CALLBACK_URL" + }, + "worker": { + "queuePriorityLevel": "QUEUE_PRIORITY_LEVEL" } } diff --git a/services/apps/integration_stream_worker/config/default.json b/services/apps/integration_stream_worker/config/default.json index 3080ea2731..8a7dc79f12 100644 --- a/services/apps/integration_stream_worker/config/default.json +++ b/services/apps/integration_stream_worker/config/default.json @@ -2,9 +2,11 @@ "db": {}, "sqs": {}, "redis": {}, + "unleash": {}, "nango": {}, "worker": { - "maxStreamRetries": 5 + "maxStreamRetries": 5, + "queuePriorityLevel": "normal" }, "slack": { "maxRetrospectInSeconds": 86400 diff --git a/services/apps/integration_stream_worker/package.json b/services/apps/integration_stream_worker/package.json index 4ade14aa08..a7016eb9d0 100644 --- a/services/apps/integration_stream_worker/package.json +++ b/services/apps/integration_stream_worker/package.json @@ -16,7 +16,7 @@ "script:process-webhook": "SERVICE=script TS_NODE_TRANSPILE_ONLY=true node -r tsconfig-paths/register -r ts-node/register src/bin/process-webhook.ts", "script:process-all-streams": "SERVICE=script TS_NODE_TRANSPILE_ONLY=true node -r tsconfig-paths/register -r ts-node/register src/bin/process-all-streams.ts", "script:process-all-webhooks": "SERVICE=script TS_NODE_TRANSPILE_ONLY=true node -r tsconfig-paths/register -r ts-node/register src/bin/process-all-webhooks.ts", - "script:trigger-all-failed-webhooks": "SERVICE=script TS_NODE_TRANSPILE_ONLY=true node -r tsconfig-paths/register -r ts-node/register src/bin/process-all-failed-webhooks.ts", + "script:trigger-all-failed-webhooks": "SERVICE=script TS_NODE_TRANSPILE_ONLY=true node -r tsconfig-paths/register -r ts-node/register src/bin/trigger-all-failed-webhooks.ts", "script:trigger-webhook": "SERVICE=script TS_NODE_TRANSPILE_ONLY=true node -r tsconfig-paths/register -r ts-node/register src/bin/process-webhook.ts", "script:trigger-all-streams": "SERVICE=script TS_NODE_TRANSPILE_ONLY=true node -r tsconfig-paths/register -r ts-node/register src/bin/trigger-all-streams.ts", "script:trigger-all-streams-for-integration": "SERVICE=script TS_NODE_TRANSPILE_ONLY=true node -r tsconfig-paths/register -r ts-node/register src/bin/trigger-all-streams-for-integration.ts", @@ -31,6 +31,8 @@ "@crowd/sqs": "file:../../libs/sqs", "@crowd/tracing": "file:../../libs/tracing", "@crowd/types": "file:../../libs/types", + "@crowd/feature-flags": "file:../../libs/feature-flags", + "@crowd/common_services": "file:../../libs/common_services", "@types/config": "^3.3.0", "@types/node": "^18.16.3", "config": "^3.3.9", diff --git a/services/apps/integration_stream_worker/src/bin/process-all-streams-for-integration.ts b/services/apps/integration_stream_worker/src/bin/process-all-streams-for-integration.ts index 4444fdb9aa..ce2d980bc5 100644 --- a/services/apps/integration_stream_worker/src/bin/process-all-streams-for-integration.ts +++ b/services/apps/integration_stream_worker/src/bin/process-all-streams-for-integration.ts @@ -1,17 +1,20 @@ -import { DB_CONFIG, REDIS_CONFIG, SQS_CONFIG } from '../conf' +import { DB_CONFIG, REDIS_CONFIG, SQS_CONFIG, UNLEASH_CONFIG } from '../conf' import IntegrationStreamService from '../service/integrationStreamService' import { timeout } from '@crowd/common' import { DbStore, getDbConnection } from '@crowd/database' import { getServiceTracer } from '@crowd/tracing' import { getServiceLogger } from '@crowd/logging' import { getRedisClient } from '@crowd/redis' +import { getSqsClient } from '@crowd/sqs' +import { IntegrationStreamState } from '@crowd/types' import { IntegrationDataWorkerEmitter, IntegrationRunWorkerEmitter, IntegrationStreamWorkerEmitter, - getSqsClient, -} from '@crowd/sqs' -import { IntegrationStreamState } from '@crowd/types' + PriorityLevelContextRepository, + QueuePriorityContextLoader, +} from '@crowd/common_services' +import { getUnleashClient } from '@crowd/feature-flags' const BATCH_SIZE = 100 const MAX_CONCURRENT = 1 @@ -41,19 +44,43 @@ async function processStream( setImmediate(async () => { const sqsClient = getSqsClient(SQS_CONFIG()) - + const dbConnection = await getDbConnection(DB_CONFIG()) + const store = new DbStore(log, dbConnection) + const unleash = await getUnleashClient(UNLEASH_CONFIG()) const redisClient = await getRedisClient(REDIS_CONFIG(), true) - const runWorkerEmiiter = new IntegrationRunWorkerEmitter(sqsClient, tracer, log) - const dataWorkerEmitter = new IntegrationDataWorkerEmitter(sqsClient, tracer, log) - const streamWorkerEmitter = new IntegrationStreamWorkerEmitter(sqsClient, tracer, log) + const priorityLevelRepo = new PriorityLevelContextRepository(store, log) + const loader: QueuePriorityContextLoader = (tenantId: string) => + priorityLevelRepo.loadPriorityLevelContext(tenantId) + + const runWorkerEmiiter = new IntegrationRunWorkerEmitter( + sqsClient, + redisClient, + tracer, + unleash, + loader, + log, + ) + const dataWorkerEmitter = new IntegrationDataWorkerEmitter( + sqsClient, + redisClient, + tracer, + unleash, + loader, + log, + ) + const streamWorkerEmitter = new IntegrationStreamWorkerEmitter( + sqsClient, + redisClient, + tracer, + unleash, + loader, + log, + ) await runWorkerEmiiter.init() await dataWorkerEmitter.init() await streamWorkerEmitter.init() - const dbConnection = await getDbConnection(DB_CONFIG()) - const store = new DbStore(log, dbConnection) - const service = new IntegrationStreamService( redisClient, runWorkerEmiiter, diff --git a/services/apps/integration_stream_worker/src/bin/process-all-streams.ts b/services/apps/integration_stream_worker/src/bin/process-all-streams.ts index 4c80b39803..8d8475633c 100644 --- a/services/apps/integration_stream_worker/src/bin/process-all-streams.ts +++ b/services/apps/integration_stream_worker/src/bin/process-all-streams.ts @@ -1,17 +1,20 @@ -import { DB_CONFIG, REDIS_CONFIG, SQS_CONFIG } from '../conf' +import { DB_CONFIG, REDIS_CONFIG, SQS_CONFIG, UNLEASH_CONFIG } from '../conf' import IntegrationStreamService from '../service/integrationStreamService' import { timeout } from '@crowd/common' import { DbStore, getDbConnection } from '@crowd/database' import { getServiceTracer } from '@crowd/tracing' import { getServiceLogger } from '@crowd/logging' import { getRedisClient } from '@crowd/redis' +import { getSqsClient } from '@crowd/sqs' +import { IntegrationStreamState } from '@crowd/types' import { IntegrationDataWorkerEmitter, IntegrationRunWorkerEmitter, IntegrationStreamWorkerEmitter, - getSqsClient, -} from '@crowd/sqs' -import { IntegrationStreamState } from '@crowd/types' + PriorityLevelContextRepository, + QueuePriorityContextLoader, +} from '@crowd/common_services' +import { getUnleashClient } from '@crowd/feature-flags' const BATCH_SIZE = 100 const MAX_CONCURRENT = 3 @@ -32,19 +35,43 @@ async function processStream( setImmediate(async () => { const sqsClient = getSqsClient(SQS_CONFIG()) - + const dbConnection = await getDbConnection(DB_CONFIG()) + const store = new DbStore(log, dbConnection) const redisClient = await getRedisClient(REDIS_CONFIG(), true) - const runWorkerEmiiter = new IntegrationRunWorkerEmitter(sqsClient, tracer, log) - const dataWorkerEmitter = new IntegrationDataWorkerEmitter(sqsClient, tracer, log) - const streamWorkerEmitter = new IntegrationStreamWorkerEmitter(sqsClient, tracer, log) + const unleash = await getUnleashClient(UNLEASH_CONFIG()) + const priorityLevelRepo = new PriorityLevelContextRepository(new DbStore(log, dbConnection), log) + const loader: QueuePriorityContextLoader = (tenantId: string) => + priorityLevelRepo.loadPriorityLevelContext(tenantId) + + const runWorkerEmiiter = new IntegrationRunWorkerEmitter( + sqsClient, + redisClient, + tracer, + unleash, + loader, + log, + ) + const dataWorkerEmitter = new IntegrationDataWorkerEmitter( + sqsClient, + redisClient, + tracer, + unleash, + loader, + log, + ) + const streamWorkerEmitter = new IntegrationStreamWorkerEmitter( + sqsClient, + redisClient, + tracer, + unleash, + loader, + log, + ) await runWorkerEmiiter.init() await dataWorkerEmitter.init() await streamWorkerEmitter.init() - const dbConnection = await getDbConnection(DB_CONFIG()) - const store = new DbStore(log, dbConnection) - const service = new IntegrationStreamService( redisClient, runWorkerEmiiter, diff --git a/services/apps/integration_stream_worker/src/bin/process-all-webhooks.ts b/services/apps/integration_stream_worker/src/bin/process-all-webhooks.ts index abb397c285..8ce962a86e 100644 --- a/services/apps/integration_stream_worker/src/bin/process-all-webhooks.ts +++ b/services/apps/integration_stream_worker/src/bin/process-all-webhooks.ts @@ -1,17 +1,20 @@ -import { DB_CONFIG, REDIS_CONFIG, SQS_CONFIG } from '../conf' +import { DB_CONFIG, REDIS_CONFIG, SQS_CONFIG, UNLEASH_CONFIG } from '../conf' import IntegrationStreamService from '../service/integrationStreamService' import { timeout } from '@crowd/common' import { DbStore, getDbConnection } from '@crowd/database' import { getServiceTracer } from '@crowd/tracing' import { getServiceLogger } from '@crowd/logging' import { getRedisClient } from '@crowd/redis' +import { getSqsClient } from '@crowd/sqs' +import { WebhookType } from '@crowd/types' import { IntegrationDataWorkerEmitter, IntegrationRunWorkerEmitter, IntegrationStreamWorkerEmitter, - getSqsClient, -} from '@crowd/sqs' -import { WebhookType } from '@crowd/types' + PriorityLevelContextRepository, + QueuePriorityContextLoader, +} from '@crowd/common_services' +import { getUnleashClient } from '@crowd/feature-flags' const BATCH_SIZE = 100 const MAX_CONCURRENT = 3 @@ -32,19 +35,43 @@ async function processWebhook( setImmediate(async () => { const sqsClient = getSqsClient(SQS_CONFIG()) + const dbConnection = await getDbConnection(DB_CONFIG()) + const store = new DbStore(log, dbConnection) + const unleash = await getUnleashClient(UNLEASH_CONFIG()) + const priorityLevelRepo = new PriorityLevelContextRepository(new DbStore(log, dbConnection), log) + const loader: QueuePriorityContextLoader = (tenantId: string) => + priorityLevelRepo.loadPriorityLevelContext(tenantId) const redisClient = await getRedisClient(REDIS_CONFIG(), true) - const runWorkerEmiiter = new IntegrationRunWorkerEmitter(sqsClient, tracer, log) - const dataWorkerEmitter = new IntegrationDataWorkerEmitter(sqsClient, tracer, log) - const streamWorkerEmitter = new IntegrationStreamWorkerEmitter(sqsClient, tracer, log) + const runWorkerEmiiter = new IntegrationRunWorkerEmitter( + sqsClient, + redisClient, + tracer, + unleash, + loader, + log, + ) + const dataWorkerEmitter = new IntegrationDataWorkerEmitter( + sqsClient, + redisClient, + tracer, + unleash, + loader, + log, + ) + const streamWorkerEmitter = new IntegrationStreamWorkerEmitter( + sqsClient, + redisClient, + tracer, + unleash, + loader, + log, + ) await runWorkerEmiiter.init() await dataWorkerEmitter.init() await streamWorkerEmitter.init() - const dbConnection = await getDbConnection(DB_CONFIG()) - const store = new DbStore(log, dbConnection) - const service = new IntegrationStreamService( redisClient, runWorkerEmiiter, diff --git a/services/apps/integration_stream_worker/src/bin/process-stream.ts b/services/apps/integration_stream_worker/src/bin/process-stream.ts index fcdd65e14e..104e856680 100644 --- a/services/apps/integration_stream_worker/src/bin/process-stream.ts +++ b/services/apps/integration_stream_worker/src/bin/process-stream.ts @@ -1,17 +1,20 @@ -import { DB_CONFIG, REDIS_CONFIG, SQS_CONFIG } from '../conf' +import { DB_CONFIG, REDIS_CONFIG, SQS_CONFIG, UNLEASH_CONFIG } from '../conf' import IntegrationStreamRepository from '../repo/integrationStream.repo' import IntegrationStreamService from '../service/integrationStreamService' import { DbStore, getDbConnection } from '@crowd/database' import { getServiceTracer } from '@crowd/tracing' import { getServiceLogger } from '@crowd/logging' import { getRedisClient } from '@crowd/redis' +import { getSqsClient } from '@crowd/sqs' +import { IntegrationStreamState } from '@crowd/types' import { IntegrationDataWorkerEmitter, IntegrationRunWorkerEmitter, IntegrationStreamWorkerEmitter, - getSqsClient, -} from '@crowd/sqs' -import { IntegrationStreamState } from '@crowd/types' + PriorityLevelContextRepository, + QueuePriorityContextLoader, +} from '@crowd/common_services' +import { getUnleashClient } from '@crowd/feature-flags' const tracer = getServiceTracer() const log = getServiceLogger() @@ -27,18 +30,43 @@ const streamIds = processArguments[0].split(',') setImmediate(async () => { const sqsClient = getSqsClient(SQS_CONFIG()) + const unleash = await getUnleashClient(UNLEASH_CONFIG()) + const dbConnection = await getDbConnection(DB_CONFIG()) + const store = new DbStore(log, dbConnection) + const priorityLevelRepo = new PriorityLevelContextRepository(store, log) + const loader: QueuePriorityContextLoader = (tenantId: string) => + priorityLevelRepo.loadPriorityLevelContext(tenantId) const redisClient = await getRedisClient(REDIS_CONFIG(), true) - const runWorkerEmiiter = new IntegrationRunWorkerEmitter(sqsClient, tracer, log) - const dataWorkerEmitter = new IntegrationDataWorkerEmitter(sqsClient, tracer, log) - const streamWorkerEmitter = new IntegrationStreamWorkerEmitter(sqsClient, tracer, log) + const runWorkerEmiiter = new IntegrationRunWorkerEmitter( + sqsClient, + redisClient, + tracer, + unleash, + loader, + log, + ) + const dataWorkerEmitter = new IntegrationDataWorkerEmitter( + sqsClient, + redisClient, + tracer, + unleash, + loader, + log, + ) + const streamWorkerEmitter = new IntegrationStreamWorkerEmitter( + sqsClient, + redisClient, + tracer, + unleash, + loader, + log, + ) await runWorkerEmiiter.init() await dataWorkerEmitter.init() await streamWorkerEmitter.init() - const dbConnection = await getDbConnection(DB_CONFIG()) - const store = new DbStore(log, dbConnection) const repo = new IntegrationStreamRepository(store, log) const service = new IntegrationStreamService( diff --git a/services/apps/integration_stream_worker/src/bin/process-webhook.ts b/services/apps/integration_stream_worker/src/bin/process-webhook.ts index c504e39a02..4afba27f22 100644 --- a/services/apps/integration_stream_worker/src/bin/process-webhook.ts +++ b/services/apps/integration_stream_worker/src/bin/process-webhook.ts @@ -1,15 +1,18 @@ -import { DB_CONFIG, REDIS_CONFIG, SQS_CONFIG } from '../conf' +import { DB_CONFIG, REDIS_CONFIG, SQS_CONFIG, UNLEASH_CONFIG } from '../conf' import IntegrationStreamService from '../service/integrationStreamService' import { DbStore, getDbConnection } from '@crowd/database' import { getServiceTracer } from '@crowd/tracing' import { getServiceLogger } from '@crowd/logging' import { getRedisClient } from '@crowd/redis' +import { getSqsClient } from '@crowd/sqs' import { IntegrationDataWorkerEmitter, IntegrationRunWorkerEmitter, IntegrationStreamWorkerEmitter, - getSqsClient, -} from '@crowd/sqs' + PriorityLevelContextRepository, + QueuePriorityContextLoader, +} from '@crowd/common_services' +import { getUnleashClient } from '@crowd/feature-flags' const tracer = getServiceTracer() const log = getServiceLogger() @@ -25,19 +28,43 @@ const webhookIds = processArguments[0].split(',') setImmediate(async () => { const sqsClient = getSqsClient(SQS_CONFIG()) - + const dbConnection = await getDbConnection(DB_CONFIG()) + const store = new DbStore(log, dbConnection) + const unleash = await getUnleashClient(UNLEASH_CONFIG()) const redisClient = await getRedisClient(REDIS_CONFIG(), true) - const runWorkerEmiiter = new IntegrationRunWorkerEmitter(sqsClient, tracer, log) - const dataWorkerEmitter = new IntegrationDataWorkerEmitter(sqsClient, tracer, log) - const streamWorkerEmitter = new IntegrationStreamWorkerEmitter(sqsClient, tracer, log) + const priorityLevelRepo = new PriorityLevelContextRepository(store, log) + const loader: QueuePriorityContextLoader = (tenantId: string) => + priorityLevelRepo.loadPriorityLevelContext(tenantId) + + const runWorkerEmiiter = new IntegrationRunWorkerEmitter( + sqsClient, + redisClient, + tracer, + unleash, + loader, + log, + ) + const dataWorkerEmitter = new IntegrationDataWorkerEmitter( + sqsClient, + redisClient, + tracer, + unleash, + loader, + log, + ) + const streamWorkerEmitter = new IntegrationStreamWorkerEmitter( + sqsClient, + redisClient, + tracer, + unleash, + loader, + log, + ) await runWorkerEmiiter.init() await dataWorkerEmitter.init() await streamWorkerEmitter.init() - const dbConnection = await getDbConnection(DB_CONFIG()) - const store = new DbStore(log, dbConnection) - const service = new IntegrationStreamService( redisClient, runWorkerEmiiter, diff --git a/services/apps/integration_stream_worker/src/bin/trigger-all-failed-webhooks.ts b/services/apps/integration_stream_worker/src/bin/trigger-all-failed-webhooks.ts index 41793572e2..373e49cdf7 100644 --- a/services/apps/integration_stream_worker/src/bin/trigger-all-failed-webhooks.ts +++ b/services/apps/integration_stream_worker/src/bin/trigger-all-failed-webhooks.ts @@ -1,9 +1,16 @@ -import { DB_CONFIG, SQS_CONFIG } from '../conf' +import { DB_CONFIG, REDIS_CONFIG, SQS_CONFIG, UNLEASH_CONFIG } from '../conf' import IncomingWebhookRepository from '../repo/incomingWebhook.repo' import { DbStore, getDbConnection } from '@crowd/database' import { getServiceTracer } from '@crowd/tracing' import { getServiceLogger } from '@crowd/logging' -import { IntegrationStreamWorkerEmitter, getSqsClient } from '@crowd/sqs' +import { getSqsClient } from '@crowd/sqs' +import { + PriorityLevelContextRepository, + QueuePriorityContextLoader, + IntegrationStreamWorkerEmitter, +} from '@crowd/common_services' +import { getUnleashClient } from '@crowd/feature-flags' +import { getRedisClient } from '@crowd/redis' const batchSize = 500 @@ -12,12 +19,24 @@ const log = getServiceLogger() setImmediate(async () => { const sqsClient = getSqsClient(SQS_CONFIG()) - const emitter = new IntegrationStreamWorkerEmitter(sqsClient, tracer, log) - await emitter.init() - const dbConnection = await getDbConnection(DB_CONFIG()) const store = new DbStore(log, dbConnection) + const unleash = await getUnleashClient(UNLEASH_CONFIG()) + const redisClient = await getRedisClient(REDIS_CONFIG(), true) + const priorityLevelRepo = new PriorityLevelContextRepository(store, log) + const loader: QueuePriorityContextLoader = (tenantId: string) => + priorityLevelRepo.loadPriorityLevelContext(tenantId) + const emitter = new IntegrationStreamWorkerEmitter( + sqsClient, + redisClient, + tracer, + unleash, + loader, + log, + ) + await emitter.init() + const repo = new IncomingWebhookRepository(store, log) let count = 0 diff --git a/services/apps/integration_stream_worker/src/bin/trigger-all-streams-for-integration.ts b/services/apps/integration_stream_worker/src/bin/trigger-all-streams-for-integration.ts index 3534329897..fe1a0300ad 100644 --- a/services/apps/integration_stream_worker/src/bin/trigger-all-streams-for-integration.ts +++ b/services/apps/integration_stream_worker/src/bin/trigger-all-streams-for-integration.ts @@ -1,8 +1,15 @@ -import { DB_CONFIG, SQS_CONFIG } from '../conf' -import { getDbConnection } from '@crowd/database' +import { DB_CONFIG, REDIS_CONFIG, SQS_CONFIG, UNLEASH_CONFIG } from '../conf' +import { DbStore, getDbConnection } from '@crowd/database' import { getServiceTracer } from '@crowd/tracing' import { getServiceLogger } from '@crowd/logging' -import { IntegrationStreamWorkerEmitter, getSqsClient } from '@crowd/sqs' +import { getSqsClient } from '@crowd/sqs' +import { getUnleashClient } from '@crowd/feature-flags' +import { + PriorityLevelContextRepository, + QueuePriorityContextLoader, + IntegrationStreamWorkerEmitter, +} from '@crowd/common_services' +import { getRedisClient } from '@crowd/redis' const BATCH_SIZE = 100 @@ -20,16 +27,28 @@ const integrationId = processArguments[0] setImmediate(async () => { const sqsClient = getSqsClient(SQS_CONFIG()) + const dbConnection = await getDbConnection(DB_CONFIG()) + const unleash = await getUnleashClient(UNLEASH_CONFIG()) + const redisClient = await getRedisClient(REDIS_CONFIG(), true) + const priorityLevelRepo = new PriorityLevelContextRepository(new DbStore(log, dbConnection), log) + const loader: QueuePriorityContextLoader = (tenantId: string) => + priorityLevelRepo.loadPriorityLevelContext(tenantId) - const emitter = new IntegrationStreamWorkerEmitter(sqsClient, tracer, log) + const emitter = new IntegrationStreamWorkerEmitter( + sqsClient, + redisClient, + tracer, + unleash, + loader, + log, + ) await emitter.init() - const dbConnection = await getDbConnection(DB_CONFIG()) - let results = await dbConnection.any( ` - select s.id + select s.id, r.onboarding from integration.streams s + left join integration.runs r on r.id = s."runId" where state in ('error', 'pending', 'processing') and s."integrationId" = $(integrationId) order by s.id @@ -43,15 +62,16 @@ setImmediate(async () => { let count = 0 while (results.length > 0) { for (const result of results) { - await emitter.triggerStreamProcessing(result.id, result.id, result.id) + await emitter.triggerStreamProcessing(result.id, result.id, result.id, result.onboarding) } count += results.length log.info(`Processed total of ${count} streams for integration ${integrationId}!`) results = await dbConnection.any( ` - select s.id + select s.id, r.onboarding from integration.streams s + left join integration.runs r on r.id = s."runId" where state in ('error', 'pending', 'processing') and s."integrationId" = $(integrationId) and s.id > $(lastId) diff --git a/services/apps/integration_stream_worker/src/bin/trigger-all-streams.ts b/services/apps/integration_stream_worker/src/bin/trigger-all-streams.ts index dcbe3a5880..dd4d8cd60c 100644 --- a/services/apps/integration_stream_worker/src/bin/trigger-all-streams.ts +++ b/services/apps/integration_stream_worker/src/bin/trigger-all-streams.ts @@ -1,8 +1,15 @@ -import { DB_CONFIG, SQS_CONFIG } from '../conf' -import { getDbConnection } from '@crowd/database' +import { DB_CONFIG, REDIS_CONFIG, SQS_CONFIG, UNLEASH_CONFIG } from '../conf' +import { DbStore, getDbConnection } from '@crowd/database' import { getServiceTracer } from '@crowd/tracing' import { getServiceLogger } from '@crowd/logging' -import { IntegrationStreamWorkerEmitter, getSqsClient } from '@crowd/sqs' +import { getSqsClient } from '@crowd/sqs' +import { + PriorityLevelContextRepository, + QueuePriorityContextLoader, + IntegrationStreamWorkerEmitter, +} from '@crowd/common_services' +import { getUnleashClient } from '@crowd/feature-flags' +import { getRedisClient } from '@crowd/redis' const BATCH_SIZE = 100 @@ -11,16 +18,28 @@ const log = getServiceLogger() setImmediate(async () => { const sqsClient = getSqsClient(SQS_CONFIG()) + const dbConnection = await getDbConnection(DB_CONFIG()) + const unleash = await getUnleashClient(UNLEASH_CONFIG()) + const redisClient = await getRedisClient(REDIS_CONFIG(), true) + const priorityLevelRepo = new PriorityLevelContextRepository(new DbStore(log, dbConnection), log) + const loader: QueuePriorityContextLoader = (tenantId: string) => + priorityLevelRepo.loadPriorityLevelContext(tenantId) - const emitter = new IntegrationStreamWorkerEmitter(sqsClient, tracer, log) + const emitter = new IntegrationStreamWorkerEmitter( + sqsClient, + redisClient, + tracer, + unleash, + loader, + log, + ) await emitter.init() - const dbConnection = await getDbConnection(DB_CONFIG()) - let results = await dbConnection.any( ` - select s.id + select s.id, r.onboarding from integration.streams s + left join integration.runs r on r.id = s."runId" where state in ('error', 'pending', 'processing') order by s.id limit ${BATCH_SIZE}; @@ -30,15 +49,16 @@ setImmediate(async () => { let count = 0 while (results.length > 0) { for (const result of results) { - await emitter.triggerStreamProcessing(result.id, result.id, result.id) + await emitter.triggerStreamProcessing(result.id, result.id, result.id, result.onboarding) } count += results.length log.info(`Processed total of ${count} streams!`) results = await dbConnection.any( ` - select s.id + select s.id, r.onboarding from integration.streams s + left join integration.runs r on r.id = s."runId" where state in ('error', 'pending', 'processing') and s.id > $(lastId) order by s.id diff --git a/services/apps/integration_stream_worker/src/bin/trigger-webhook.ts b/services/apps/integration_stream_worker/src/bin/trigger-webhook.ts index 7741d0399a..01b3a1b6cc 100644 --- a/services/apps/integration_stream_worker/src/bin/trigger-webhook.ts +++ b/services/apps/integration_stream_worker/src/bin/trigger-webhook.ts @@ -1,10 +1,17 @@ -import { DB_CONFIG, SQS_CONFIG } from '../conf' +import { DB_CONFIG, REDIS_CONFIG, SQS_CONFIG, UNLEASH_CONFIG } from '../conf' import IncomingWebhookRepository from '../repo/incomingWebhook.repo' import { DbStore, getDbConnection } from '@crowd/database' import { getServiceTracer } from '@crowd/tracing' import { getServiceLogger } from '@crowd/logging' -import { IntegrationStreamWorkerEmitter, getSqsClient } from '@crowd/sqs' +import { getSqsClient } from '@crowd/sqs' import { WebhookState, WebhookType } from '@crowd/types' +import { + IntegrationStreamWorkerEmitter, + PriorityLevelContextRepository, + QueuePriorityContextLoader, +} from '@crowd/common_services' +import { getUnleashClient } from '@crowd/feature-flags' +import { getRedisClient } from '@crowd/redis' const tracer = getServiceTracer() const log = getServiceLogger() @@ -19,12 +26,27 @@ if (processArguments.length !== 1) { const webhookIds = processArguments[0].split(',') setImmediate(async () => { - const sqsClient = getSqsClient(SQS_CONFIG()) - const emitter = new IntegrationStreamWorkerEmitter(sqsClient, tracer, log) - await emitter.init() + const unleash = await getUnleashClient(UNLEASH_CONFIG()) + const redisClient = await getRedisClient(REDIS_CONFIG(), true) const dbConnection = await getDbConnection(DB_CONFIG()) const store = new DbStore(log, dbConnection) + + const priorityLevelRepo = new PriorityLevelContextRepository(store, log) + const loader: QueuePriorityContextLoader = (tenantId: string) => + priorityLevelRepo.loadPriorityLevelContext(tenantId) + + const sqsClient = getSqsClient(SQS_CONFIG()) + const emitter = new IntegrationStreamWorkerEmitter( + sqsClient, + redisClient, + tracer, + unleash, + loader, + log, + ) + await emitter.init() + const repo = new IncomingWebhookRepository(store, log) for (const webhookId of webhookIds) { diff --git a/services/apps/integration_stream_worker/src/conf/index.ts b/services/apps/integration_stream_worker/src/conf/index.ts index 0d7c697a28..17f55071a7 100644 --- a/services/apps/integration_stream_worker/src/conf/index.ts +++ b/services/apps/integration_stream_worker/src/conf/index.ts @@ -1,10 +1,14 @@ +import { SERVICE } from '@crowd/common' import { IDatabaseConfig } from '@crowd/database' +import { IUnleashConfig } from '@crowd/feature-flags' import { IRedisConfiguration } from '@crowd/redis' import { ISqsClientConfig } from '@crowd/sqs' +import { QueuePriorityLevel } from '@crowd/types' import config from 'config' export interface IWorkerConfig { maxStreamRetries: number + queuePriorityLevel: QueuePriorityLevel } export interface INangoConfig { @@ -73,3 +77,12 @@ export const PLATFORM_CONFIG = (platform: string): unknown | undefined => { return undefined } } + +let unleashConfig: IUnleashConfig | undefined +export const UNLEASH_CONFIG = (): IUnleashConfig | undefined => { + if (unleashConfig) return unleashConfig + + unleashConfig = Object.assign({ appName: SERVICE }, config.get('unleash')) + + return unleashConfig +} diff --git a/services/apps/integration_stream_worker/src/jobs/processOldStreams.ts b/services/apps/integration_stream_worker/src/jobs/processOldStreams.ts index dc1cabd76d..c135a34e7e 100644 --- a/services/apps/integration_stream_worker/src/jobs/processOldStreams.ts +++ b/services/apps/integration_stream_worker/src/jobs/processOldStreams.ts @@ -1,14 +1,14 @@ import { DbConnection, DbStore } from '@crowd/database' import { Logger } from '@crowd/logging' import { RedisClient } from '@crowd/redis' +import { IInsertableWebhookStream } from '../repo/integrationStream.data' +import IntegrationStreamRepository from '../repo/integrationStream.repo' +import IntegrationStreamService from '../service/integrationStreamService' import { IntegrationDataWorkerEmitter, IntegrationRunWorkerEmitter, IntegrationStreamWorkerEmitter, -} from '@crowd/sqs' -import { IInsertableWebhookStream } from '../repo/integrationStream.data' -import IntegrationStreamRepository from '../repo/integrationStream.repo' -import IntegrationStreamService from '../service/integrationStreamService' +} from '@crowd/common_services' export const processOldStreamsJob = async ( dbConn: DbConnection, diff --git a/services/apps/integration_stream_worker/src/main.ts b/services/apps/integration_stream_worker/src/main.ts index ecae3280f0..09a0db0b12 100644 --- a/services/apps/integration_stream_worker/src/main.ts +++ b/services/apps/integration_stream_worker/src/main.ts @@ -1,16 +1,19 @@ import { getServiceTracer } from '@crowd/tracing' import { getServiceLogger } from '@crowd/logging' -import { DB_CONFIG, REDIS_CONFIG, SQS_CONFIG } from './conf' +import { DB_CONFIG, REDIS_CONFIG, SQS_CONFIG, UNLEASH_CONFIG, WORKER_SETTINGS } from './conf' import { getRedisClient } from '@crowd/redis' -import { getDbConnection } from '@crowd/database' +import { DbStore, getDbConnection } from '@crowd/database' +import { getSqsClient } from '@crowd/sqs' +import { WorkerQueueReceiver } from './queue' +import { processOldStreamsJob } from './jobs/processOldStreams' import { IntegrationRunWorkerEmitter, IntegrationDataWorkerEmitter, IntegrationStreamWorkerEmitter, - getSqsClient, -} from '@crowd/sqs' -import { WorkerQueueReceiver } from './queue' -import { processOldStreamsJob } from './jobs/processOldStreams' + PriorityLevelContextRepository, + QueuePriorityContextLoader, +} from '@crowd/common_services' +import { getUnleashClient } from '@crowd/feature-flags' const tracer = getServiceTracer() const log = getServiceLogger() @@ -21,16 +24,44 @@ const PROCESSING_INTERVAL_MINUTES = 5 setImmediate(async () => { log.info('Starting integration stream worker...') + const unleash = await getUnleashClient(UNLEASH_CONFIG()) + const sqsClient = getSqsClient(SQS_CONFIG()) const dbConnection = await getDbConnection(DB_CONFIG(), MAX_CONCURRENT_PROCESSING) const redisClient = await getRedisClient(REDIS_CONFIG(), true) - const runWorkerEmiiter = new IntegrationRunWorkerEmitter(sqsClient, tracer, log) - const dataWorkerEmitter = new IntegrationDataWorkerEmitter(sqsClient, tracer, log) - const streamWorkerEmitter = new IntegrationStreamWorkerEmitter(sqsClient, tracer, log) + const priorityLevelRepo = new PriorityLevelContextRepository(new DbStore(log, dbConnection), log) + const loader: QueuePriorityContextLoader = (tenantId: string) => + priorityLevelRepo.loadPriorityLevelContext(tenantId) + + const runWorkerEmiiter = new IntegrationRunWorkerEmitter( + sqsClient, + redisClient, + tracer, + unleash, + loader, + log, + ) + const dataWorkerEmitter = new IntegrationDataWorkerEmitter( + sqsClient, + redisClient, + tracer, + unleash, + loader, + log, + ) + const streamWorkerEmitter = new IntegrationStreamWorkerEmitter( + sqsClient, + redisClient, + tracer, + unleash, + loader, + log, + ) const queue = new WorkerQueueReceiver( + WORKER_SETTINGS().queuePriorityLevel, sqsClient, redisClient, dbConnection, diff --git a/services/apps/integration_stream_worker/src/queue/index.ts b/services/apps/integration_stream_worker/src/queue/index.ts index e74f4212b9..088550d7e9 100644 --- a/services/apps/integration_stream_worker/src/queue/index.ts +++ b/services/apps/integration_stream_worker/src/queue/index.ts @@ -1,26 +1,30 @@ -import { Tracer, Span, SpanStatusCode } from '@crowd/tracing' -import { Logger } from '@crowd/logging' -import { DbConnection, DbStore } from '@crowd/database' import { - INTEGRATION_STREAM_WORKER_QUEUE_SETTINGS, - IntegrationRunWorkerEmitter, IntegrationDataWorkerEmitter, + IntegrationRunWorkerEmitter, IntegrationStreamWorkerEmitter, +} from '@crowd/common_services' +import { DbConnection, DbStore } from '@crowd/database' +import { Logger } from '@crowd/logging' +import { RedisClient } from '@crowd/redis' +import { + INTEGRATION_STREAM_WORKER_QUEUE_SETTINGS, SqsClient, - SqsQueueReceiver, + SqsPrioritizedQueueReciever, } from '@crowd/sqs' +import { Span, SpanStatusCode, Tracer } from '@crowd/tracing' import { ContinueProcessingRunStreamsQueueMessage, IQueueMessage, IntegrationStreamWorkerQueueMessageType, ProcessStreamQueueMessage, ProcessWebhookStreamQueueMessage, + QueuePriorityLevel, } from '@crowd/types' -import { RedisClient } from '@crowd/redis' import IntegrationStreamService from '../service/integrationStreamService' -export class WorkerQueueReceiver extends SqsQueueReceiver { +export class WorkerQueueReceiver extends SqsPrioritizedQueueReciever { constructor( + level: QueuePriorityLevel, client: SqsClient, private readonly redisClient: RedisClient, private readonly dbConn: DbConnection, @@ -32,6 +36,7 @@ export class WorkerQueueReceiver extends SqsQueueReceiver { maxConcurrentProcessing: number, ) { super( + level, client, INTEGRATION_STREAM_WORKER_QUEUE_SETTINGS, maxConcurrentProcessing, diff --git a/services/apps/integration_stream_worker/src/repo/integrationStream.data.ts b/services/apps/integration_stream_worker/src/repo/integrationStream.data.ts index a7c4352265..8d7f30625e 100644 --- a/services/apps/integration_stream_worker/src/repo/integrationStream.data.ts +++ b/services/apps/integration_stream_worker/src/repo/integrationStream.data.ts @@ -29,6 +29,7 @@ export interface IProcessableStream { integrationType: string runId: string | null webhookId: string | null + onboarding: boolean | null } export interface IInsertableWebhookStream { diff --git a/services/apps/integration_stream_worker/src/repo/integrationStream.repo.ts b/services/apps/integration_stream_worker/src/repo/integrationStream.repo.ts index 9e08f9ce26..a119cec9fe 100644 --- a/services/apps/integration_stream_worker/src/repo/integrationStream.repo.ts +++ b/services/apps/integration_stream_worker/src/repo/integrationStream.repo.ts @@ -128,9 +128,11 @@ export default class IntegrationStreamRepository extends RepositoryBase $(lastId) order by s.id limit ${limit} @@ -173,9 +177,11 @@ export default class IntegrationStreamRepository extends RepositoryBase { await this.updateIntegrationSettings(streamId, settings) @@ -571,6 +581,7 @@ export default class IntegrationStreamService extends LoggerBase { streamInfo.tenantId, streamInfo.integrationType, streamInfo.runId, + streamInfo.onboarding, ) } } @@ -638,6 +649,7 @@ export default class IntegrationStreamService extends LoggerBase { platform: string, parentId: string, identifier: string, + onboarding: boolean, data?: unknown, runId?: string, webhookId?: string, @@ -652,7 +664,12 @@ export default class IntegrationStreamService extends LoggerBase { // publising normal stream const streamId = await this.repo.publishStream(parentId, identifier, data, runId) if (streamId) { - await this.streamWorkerEmitter.triggerStreamProcessing(tenantId, platform, streamId) + await this.streamWorkerEmitter.triggerStreamProcessing( + tenantId, + platform, + streamId, + onboarding, + ) } else { this.log.debug({ identifier }, 'Child stream already exists!') } @@ -683,13 +700,14 @@ export default class IntegrationStreamService extends LoggerBase { tenantId: string, platform: string, streamId: string, + onboarding: boolean, data: unknown, runId?: string, ): Promise { try { this.log.debug('Publishing new stream data!') const dataId = await this.repo.publishData(streamId, data) - await this.dataWorkerEmitter.triggerDataProcessing(tenantId, platform, dataId) + await this.dataWorkerEmitter.triggerDataProcessing(tenantId, platform, dataId, onboarding) } catch (err) { if (runId) { await this.triggerRunError( diff --git a/services/apps/integration_sync_worker/config/custom-environment-variables.json b/services/apps/integration_sync_worker/config/custom-environment-variables.json index aba9658dd4..c3bc716227 100644 --- a/services/apps/integration_sync_worker/config/custom-environment-variables.json +++ b/services/apps/integration_sync_worker/config/custom-environment-variables.json @@ -1,6 +1,7 @@ { "service": { - "edition": "CROWD_EDITION" + "edition": "CROWD_EDITION", + "queuePriorityLevel": "QUEUE_PRIORITY_LEVEL" }, "db": { "host": "CROWD_DB_WRITE_HOST", diff --git a/services/apps/integration_sync_worker/config/default.json b/services/apps/integration_sync_worker/config/default.json index 0d056b3639..fb3f396811 100644 --- a/services/apps/integration_sync_worker/config/default.json +++ b/services/apps/integration_sync_worker/config/default.json @@ -1,5 +1,7 @@ { - "service": {}, + "service": { + "queuePriorityLevel": "normal" + }, "db": {}, "sqs": {}, "redis": {}, diff --git a/services/apps/integration_sync_worker/package.json b/services/apps/integration_sync_worker/package.json index 2dcbe9a4e2..b673741639 100644 --- a/services/apps/integration_sync_worker/package.json +++ b/services/apps/integration_sync_worker/package.json @@ -17,7 +17,6 @@ "@crowd/common": "file:../../libs/common", "@crowd/database": "file:../../libs/database", "@crowd/logging": "file:../../libs/logging", - "@crowd/redis": "file:../../libs/redis", "@crowd/sqs": "file:../../libs/sqs", "@crowd/tracing": "file:../../libs/tracing", "@crowd/types": "file:../../libs/types", diff --git a/services/apps/integration_sync_worker/src/conf/index.ts b/services/apps/integration_sync_worker/src/conf/index.ts index 8fb612cd27..f0964b6f6e 100644 --- a/services/apps/integration_sync_worker/src/conf/index.ts +++ b/services/apps/integration_sync_worker/src/conf/index.ts @@ -1,10 +1,11 @@ import { IDatabaseConfig } from '@crowd/database' import { ISqsClientConfig } from '@crowd/sqs' -import { IOpenSearchConfig } from '@crowd/types' +import { IOpenSearchConfig, QueuePriorityLevel } from '@crowd/types' import config from 'config' export interface IServiceConfig { edition: string + queuePriorityLevel: QueuePriorityLevel } export interface INangoConfig { url: string diff --git a/services/apps/integration_sync_worker/src/main.ts b/services/apps/integration_sync_worker/src/main.ts index 89eef19f4a..e1fb251f6a 100644 --- a/services/apps/integration_sync_worker/src/main.ts +++ b/services/apps/integration_sync_worker/src/main.ts @@ -2,7 +2,7 @@ import { getDbConnection } from '@crowd/database' import { getServiceTracer } from '@crowd/tracing' import { getServiceLogger } from '@crowd/logging' import { getSqsClient } from '@crowd/sqs' -import { DB_CONFIG, OPENSEARCH_CONFIG, SQS_CONFIG } from './conf' +import { DB_CONFIG, OPENSEARCH_CONFIG, SERVICE_CONFIG, SQS_CONFIG } from './conf' import { WorkerQueueReceiver } from './queue' import { getOpensearchClient } from '@crowd/opensearch' @@ -13,7 +13,6 @@ const MAX_CONCURRENT_PROCESSING = 2 setImmediate(async () => { log.info('Starting integration sync worker...') - const sqsClient = getSqsClient(SQS_CONFIG()) const dbConnection = await getDbConnection(DB_CONFIG(), MAX_CONCURRENT_PROCESSING) @@ -21,6 +20,7 @@ setImmediate(async () => { const opensearchClient = getOpensearchClient(OPENSEARCH_CONFIG()) const worker = new WorkerQueueReceiver( + SERVICE_CONFIG().queuePriorityLevel, sqsClient, dbConnection, opensearchClient, diff --git a/services/apps/integration_sync_worker/src/queue/index.ts b/services/apps/integration_sync_worker/src/queue/index.ts index 0d6ed5a083..5822f389fd 100644 --- a/services/apps/integration_sync_worker/src/queue/index.ts +++ b/services/apps/integration_sync_worker/src/queue/index.ts @@ -1,19 +1,25 @@ -import { Tracer, Span, SpanStatusCode } from '@crowd/tracing' -import { Logger } from '@crowd/logging' import { DbConnection, DbStore } from '@crowd/database' -import { MemberSyncService } from '../service/member.sync.service' -import { OpenSearchService } from '../service/opensearch.service' -import { OrganizationSyncService } from '../service/organization.sync.service' -import { INTEGRATION_SYNC_WORKER_QUEUE_SETTINGS, SqsClient, SqsQueueReceiver } from '@crowd/sqs' +import { Logger } from '@crowd/logging' +import { + INTEGRATION_SYNC_WORKER_QUEUE_SETTINGS, + SqsClient, + SqsPrioritizedQueueReciever, +} from '@crowd/sqs' +import { Span, SpanStatusCode, Tracer } from '@crowd/tracing' import { AutomationSyncTrigger, IQueueMessage, IntegrationSyncWorkerQueueMessageType, + QueuePriorityLevel, } from '@crowd/types' import { Client } from '@opensearch-project/opensearch' +import { MemberSyncService } from '../service/member.sync.service' +import { OpenSearchService } from '../service/opensearch.service' +import { OrganizationSyncService } from '../service/organization.sync.service' -export class WorkerQueueReceiver extends SqsQueueReceiver { +export class WorkerQueueReceiver extends SqsPrioritizedQueueReciever { constructor( + level: QueuePriorityLevel, client: SqsClient, private readonly dbConn: DbConnection, private readonly openSearchClient: Client, @@ -22,6 +28,7 @@ export class WorkerQueueReceiver extends SqsQueueReceiver { maxConcurrentProcessing: number, ) { super( + level, client, INTEGRATION_SYNC_WORKER_QUEUE_SETTINGS, maxConcurrentProcessing, @@ -42,7 +49,7 @@ export class WorkerQueueReceiver extends SqsQueueReceiver { return new OrganizationSyncService(new DbStore(this.log, this.dbConn), this.log) } - protected override async processMessage(message: T): Promise { + public override async processMessage(message: T): Promise { await this.tracer.startActiveSpan('ProcessMessage', async (span: Span) => { try { this.log.trace({ messageType: message.type }, 'Processing message!') diff --git a/services/apps/integration_sync_worker/src/repo/organization.repo.ts b/services/apps/integration_sync_worker/src/repo/organization.repo.ts index 57f95b42e4..f6b86d17f8 100644 --- a/services/apps/integration_sync_worker/src/repo/organization.repo.ts +++ b/services/apps/integration_sync_worker/src/repo/organization.repo.ts @@ -223,7 +223,7 @@ export class OrganizationRepository extends RepositoryBase 'syncRemote' -> '${platform}')::boolean, false) = false and org."tenantId" = $(tenantId) and ${filterString} - order by org.name desc + order by org.id desc limit $(limit) offset $(offset); ` diff --git a/services/apps/integration_sync_worker/src/service/member.sync.service.ts b/services/apps/integration_sync_worker/src/service/member.sync.service.ts index 4444a3b215..8a12342af7 100644 --- a/services/apps/integration_sync_worker/src/service/member.sync.service.ts +++ b/services/apps/integration_sync_worker/src/service/member.sync.service.ts @@ -113,6 +113,7 @@ export class MemberSyncService extends LoggerBase { if (updated.length > 0) { const memberUpdated = updated[0] as IBatchUpdateMembersResult + await this.memberRepo.setSyncRemoteSourceId(syncRemoteId, memberUpdated.sourceId) await this.memberRepo.setLastSyncedAtBySyncRemoteId( syncRemoteId, memberUpdated.lastSyncedPayload, @@ -258,6 +259,11 @@ export class MemberSyncService extends LoggerBase { } for (const updatedMember of updated as IBatchUpdateMembersResult[]) { + await this.memberRepo.setIntegrationSourceId( + updatedMember.memberId, + integration.id, + updatedMember.sourceId, + ) await this.memberRepo.setLastSyncedAt( updatedMember.memberId, integration.id, @@ -473,6 +479,11 @@ export class MemberSyncService extends LoggerBase { } for (const updatedMember of updated as IBatchUpdateMembersResult[]) { + await this.memberRepo.setIntegrationSourceId( + updatedMember.memberId, + integration.id, + updatedMember.sourceId, + ) await this.memberRepo.setLastSyncedAt( updatedMember.memberId, integration.id, @@ -557,33 +568,35 @@ export class MemberSyncService extends LoggerBase { this.log.info(`Syncing member ${memberToSync.memberId} to ${integration.platform} remote!`) const member = await this.memberRepo.findMember(memberToSync.memberId) - let syncRemote = await this.memberRepo.findSyncRemote( - member.id, - integration.id, - automation.id, - ) + if (member) { + let syncRemote = await this.memberRepo.findSyncRemote( + member.id, + integration.id, + automation.id, + ) - // member isn't marked yet, mark it - if (!syncRemote) { - syncRemote = await this.memberRepo.markMemberForSyncing({ - integrationId: integration.id, - memberId: member.id, - metaData: null, - syncFrom: automation.id, - }) - } + // member isn't marked yet, mark it + if (!syncRemote) { + syncRemote = await this.memberRepo.markMemberForSyncing({ + integrationId: integration.id, + memberId: member.id, + metaData: null, + syncFrom: automation.id, + }) + } - if (syncRemote.sourceId) { - member.attributes = { - ...member.attributes, - sourceId: { - ...(member.attributes.sourceId || {}), - [integration.platform]: syncRemote.sourceId, - }, + if (syncRemote.sourceId) { + member.attributes = { + ...member.attributes, + sourceId: { + ...(member.attributes.sourceId || {}), + [integration.platform]: syncRemote.sourceId, + }, + } + membersToUpdate.push(member) + } else { + membersToCreate.push(member) } - membersToUpdate.push(member) - } else { - membersToCreate.push(member) } } @@ -622,6 +635,11 @@ export class MemberSyncService extends LoggerBase { } for (const updatedMember of updated as IBatchUpdateMembersResult[]) { + await this.memberRepo.setIntegrationSourceId( + updatedMember.memberId, + integration.id, + updatedMember.sourceId, + ) await this.memberRepo.setLastSyncedAt( updatedMember.memberId, integration.id, diff --git a/services/apps/merge_suggestions_worker/.eslintrc.cjs b/services/apps/merge_suggestions_worker/.eslintrc.cjs new file mode 100644 index 0000000000..25ba4e0d66 --- /dev/null +++ b/services/apps/merge_suggestions_worker/.eslintrc.cjs @@ -0,0 +1,21 @@ +module.exports = { + parser: '@typescript-eslint/parser', + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:prettier/recommended', + ], + plugins: ['@typescript-eslint', 'prettier'], + parserOptions: { + ecmaVersion: 2022, + sourceType: 'module', + }, + env: { + es6: true, + node: true, + }, + rules: { + 'prettier/prettier': 'error', + '@typescript-eslint/explicit-module-boundary-types': 'off', + }, +} diff --git a/services/apps/merge_suggestions_worker/.prettierignore b/services/apps/merge_suggestions_worker/.prettierignore new file mode 100644 index 0000000000..2b24877309 --- /dev/null +++ b/services/apps/merge_suggestions_worker/.prettierignore @@ -0,0 +1,3 @@ +dist/ +.eslintrc.cjs +.prettierrc.cjs diff --git a/services/apps/merge_suggestions_worker/.prettierrc.cjs b/services/apps/merge_suggestions_worker/.prettierrc.cjs new file mode 100644 index 0000000000..a8ca459839 --- /dev/null +++ b/services/apps/merge_suggestions_worker/.prettierrc.cjs @@ -0,0 +1,7 @@ +module.exports = { + singleQuote: true, + arrowParens: 'always', + printWidth: 100, + trailingComma: 'all', + semi: false, +} diff --git a/services/apps/merge_suggestions_worker/package.json b/services/apps/merge_suggestions_worker/package.json new file mode 100644 index 0000000000..a20050016d --- /dev/null +++ b/services/apps/merge_suggestions_worker/package.json @@ -0,0 +1,48 @@ +{ + "name": "@crowd/merge-suggestions-worker", + "version": "1.0.0", + "private": true, + "scripts": { + "start": "CROWD_TEMPORAL_TASKQUEUE=merge-suggestions SERVICE=merge-suggestions-worker TS_NODE_TRANSPILE_ONLY=true node -r tsconfig-paths/register -r ts-node/register src/main.ts", + "start:debug:local": "set -a && . ../../../backend/.env.dist.local && . ../../../backend/.env.override.local && set +a && CROWD_TEMPORAL_TASKQUEUE=merge-suggestions SERVICE=merge-suggestions-worker TS_NODE_TRANSPILE_ONLY=true LOG_LEVEL=trace node --inspect=0.0.0.0:9232 -r tsconfig-paths/register -r ts-node/register src/main.ts", + "start:debug": "CROWD_TEMPORAL_TASKQUEUE=merge-suggestions SERVICE=merge-suggestions-worker TS_NODE_TRANSPILE_ONLY=true LOG_LEVEL=trace node --inspect=0.0.0.0:9232 -r tsconfig-paths/register -r ts-node/register src/main.ts", + "dev:local": "./node_modules/.bin/nodemon --watch src --watch ../../libs --ext ts --exec pnpm run start:debug:local", + "dev": "./node_modules/.bin/nodemon --watch src --watch ../../libs --ext ts --exec pnpm run start:debug", + "lint": "./node_modules/.bin/eslint --ext .ts src --max-warnings=0", + "format": "./node_modules/.bin/prettier --write \"src/**/*.ts\"", + "format-check": "./node_modules/.bin/prettier --check .", + "tsc-check": "./node_modules/.bin/tsc --noEmit" + }, + "dependencies": { + "@crowd/archetype-standard": "file:../../archetypes/standard", + "@crowd/archetype-worker": "file:../../archetypes/worker", + "@crowd/common": "file:../../libs/common", + "@crowd/cubejs": "file:../../libs/cubejs", + "@crowd/types": "file:../../libs/types", + "@crowd/feature-flags": "file:../../libs/feature-flags", + "@sendgrid/mail": "~8.1.0", + "@temporalio/activity": "~1.8.6", + "@temporalio/client": "~1.8.6", + "@temporalio/workflow": "~1.8.6", + "axios": "~1.5.1", + "fast-levenshtein": "^3.0.0", + "html-to-text": "~9.0.5", + "lodash": "~4.17.21", + "moment": "~2.29.4", + "ts-node": "^10.9.1", + "tsconfig-paths": "^4.2.0", + "typescript": "^5.2.2", + "uuid": "~9.0.1" + }, + "devDependencies": { + "@types/node": "^20.8.2", + "@types/uuid": "~9.0.6", + "@typescript-eslint/eslint-plugin": "^6.7.4", + "@typescript-eslint/parser": "^6.7.4", + "eslint": "^8.50.0", + "eslint-config-prettier": "^9.0.0", + "eslint-plugin-prettier": "^5.0.0", + "nodemon": "^3.0.1", + "prettier": "^3.0.3" + } +} diff --git a/services/apps/merge_suggestions_worker/src/activities.ts b/services/apps/merge_suggestions_worker/src/activities.ts new file mode 100644 index 0000000000..30821bfeb7 --- /dev/null +++ b/services/apps/merge_suggestions_worker/src/activities.ts @@ -0,0 +1,17 @@ +import { getAllTenants } from './activities/getAllTenants' +import { + getMergeSuggestions, + addToMerge, + getMembers, + findTenantsLatestMemberSuggestionGeneratedAt, + updateMemberMergeSuggestionsLastGeneratedAt, +} from './activities/member-merge-suggestions/getMergeSuggestions' + +export { + getAllTenants, + getMergeSuggestions, + getMembers, + addToMerge, + findTenantsLatestMemberSuggestionGeneratedAt, + updateMemberMergeSuggestionsLastGeneratedAt, +} diff --git a/services/apps/merge_suggestions_worker/src/activities/getAllTenants.ts b/services/apps/merge_suggestions_worker/src/activities/getAllTenants.ts new file mode 100644 index 0000000000..15db9e697e --- /dev/null +++ b/services/apps/merge_suggestions_worker/src/activities/getAllTenants.ts @@ -0,0 +1,30 @@ +import { ITenant } from 'types' +import { svc } from '../main' +import TenantRepository from 'repo/tenant.repo' +import { isFeatureEnabled } from '@crowd/feature-flags' +import { FeatureFlag } from '@crowd/types' + +export async function getAllTenants(): Promise { + const tenantRepository = new TenantRepository(svc.postgres.writer.connection(), svc.log) + const tenants = await tenantRepository.getAllTenants() + + // map through the tenants array and resolve all promises + const tenantPromises: Promise[] = tenants.map(async (tenant) => + isFeatureEnabled( + FeatureFlag.TEMPORAL_MEMBER_MERGE_SUGGESTIONS, + async () => { + return { + tenantId: tenant.tenantId, + plan: tenant.plan, + } + }, + svc.unleash, + ), + ) + + // Wait for all promises to get resolved + const tenantsEnabled = await Promise.all(tenantPromises) + + // Filter out tenants where the feature is not enabled + return tenants.filter((_, index) => tenantsEnabled[index]) +} diff --git a/services/apps/merge_suggestions_worker/src/activities/member-merge-suggestions/getMergeSuggestions.ts b/services/apps/merge_suggestions_worker/src/activities/member-merge-suggestions/getMergeSuggestions.ts new file mode 100644 index 0000000000..b04a9174cc --- /dev/null +++ b/services/apps/merge_suggestions_worker/src/activities/member-merge-suggestions/getMergeSuggestions.ts @@ -0,0 +1,301 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { + IMemberPartialAggregatesOpensearch, + IMemberPartialAggregatesOpensearchRawResult, + IMemberQueryBody, + ISimilarMemberOpensearch, +} from 'types' +import { svc } from '../../main' +import { IMemberMergeSuggestion, OpenSearchIndex } from '@crowd/types' +import { calculateSimilarity } from 'utils' +import MemberMergeSuggestionsRepository from 'repo/memberMergeSuggestions.repo' + +/** + * Finds similar members of given member in a tenant + * Members are similar if: + * - they have exactly same or similar looking identities (with max levenshtein distance = 2) + * - they have exactly same emails + * - they have exactly same display name + * @param tenantId + * @param member + * @returns similar members in an array with calculated similarity score and activityEstimate + * Activity estimate is calculated by adding activity counts of both members + */ +export async function getMergeSuggestions( + tenantId: string, + member: IMemberPartialAggregatesOpensearch, +): Promise { + const mergeSuggestions: IMemberMergeSuggestion[] = [] + const memberMergeSuggestionsRepo = new MemberMergeSuggestionsRepository( + svc.postgres.writer.connection(), + svc.log, + ) + + const identitiesPartialQuery: any = { + should: [ + { + term: { + [`keyword_displayName`]: member.keyword_displayName, + }, + }, + ], + minimum_should_match: 1, + must_not: [ + { + term: { + uuid_memberId: member.uuid_memberId, + }, + }, + { + // exclude deleted members + term: { + 'obj_attributes.obj_isDeleted.bool_default': true, + }, + }, + ], + must: [ + { + term: { + uuid_tenantId: tenantId, + }, + }, + ], + } + + if (member.nested_identities && member.nested_identities.length > 0) { + // push nested search scaffold for weak identities + identitiesPartialQuery.should.push({ + nested: { + path: 'nested_weakIdentities', + query: { + bool: { + should: [], + boost: 1000, + minimum_should_match: 1, + }, + }, + }, + }) + + // push nested search scaffold for strong identities + identitiesPartialQuery.should.push({ + nested: { + path: 'nested_identities', + query: { + bool: { + should: [], + boost: 1, + minimum_should_match: 1, + }, + }, + }, + }) + + let hasFuzzySearch = false + + // prevent processing more than 200 identities because of opensearch limits + for (const identity of member.nested_identities.slice(0, 200)) { + if (identity.string_username.length > 0) { + // weak identity search + identitiesPartialQuery.should[1].nested.query.bool.should.push({ + bool: { + must: [ + { match: { [`nested_weakIdentities.keyword_name`]: identity.string_username } }, + { + match: { + [`nested_weakIdentities.string_platform`]: identity.string_platform, + }, + }, + ], + }, + }) + + // some identities have https? in the beginning, resulting in false positive suggestions + // remove these when making fuzzy and wildcard searches + const cleanedIdentityName = identity.string_username.replace(/^https?:\/\//, '') + + if (Number.isNaN(Number(identity.string_username))) { + hasFuzzySearch = true + // fuzzy search for identities + identitiesPartialQuery.should[2].nested.query.bool.should.push({ + match: { + [`nested_identities.string_username`]: { + query: cleanedIdentityName, + prefix_length: 1, + fuzziness: 'auto', + }, + }, + }) + } + } + } + + // check if we have any actual identity searches, if not remove it from the query + if (!hasFuzzySearch) { + identitiesPartialQuery.should.pop() + } + } + + if (member.string_arr_emails && member.string_arr_emails.length > 0) { + identitiesPartialQuery.should.push({ + terms: { + keyword_emails: member.string_arr_emails.filter((email: string) => email && email !== null), + }, + }) + } + + const noMergeIds = await memberMergeSuggestionsRepo.findNoMergeIds(member.uuid_memberId) + + if (noMergeIds && noMergeIds.length > 0) { + for (const noMergeId of noMergeIds) { + identitiesPartialQuery.must_not.push({ + term: { + uuid_memberId: noMergeId, + }, + }) + } + } + + const similarMembersQueryBody = { + query: { + bool: identitiesPartialQuery, + }, + collapse: { + field: 'uuid_memberId', + }, + _source: [ + 'uuid_memberId', + 'nested_identities', + 'nested_weakIdentities', + 'keyword_displayName', + 'string_arr_emails', + 'int_activityCount', + ], + } + + let membersToMerge: ISimilarMemberOpensearch[] + + try { + membersToMerge = + ( + await svc.opensearch.client.search({ + index: OpenSearchIndex.MEMBERS, + body: similarMembersQueryBody, + }) + ).body?.hits?.hits || [] + } catch (e) { + svc.log.info( + { error: e, query: identitiesPartialQuery }, + 'Error while searching for similar members!', + ) + throw e + } + + for (const memberToMerge of membersToMerge) { + mergeSuggestions.push({ + similarity: calculateSimilarity(member, memberToMerge._source), + activityEstimate: + (memberToMerge._source.int_activityCount || 0) + (member.int_activityCount || 0), + members: [member.uuid_memberId, memberToMerge._source.uuid_memberId], + }) + } + + return mergeSuggestions +} + +export async function addToMerge(suggestions: IMemberMergeSuggestion[]): Promise { + const memberMergeSuggestionsRepo = new MemberMergeSuggestionsRepository( + svc.postgres.writer.connection(), + svc.log, + ) + await memberMergeSuggestionsRepo.addToMerge(suggestions) +} + +export async function findTenantsLatestMemberSuggestionGeneratedAt( + tenantId: string, +): Promise { + const memberMergeSuggestionsRepo = new MemberMergeSuggestionsRepository( + svc.postgres.writer.connection(), + svc.log, + ) + return memberMergeSuggestionsRepo.findTenantsLatestMemberSuggestionGeneratedAt(tenantId) +} + +export async function updateMemberMergeSuggestionsLastGeneratedAt(tenantId: string): Promise { + const memberMergeSuggestionsRepo = new MemberMergeSuggestionsRepository( + svc.postgres.writer.connection(), + svc.log, + ) + await memberMergeSuggestionsRepo.updateMemberMergeSuggestionsLastGeneratedAt(tenantId) +} + +export async function getMembers( + tenantId: string, + batchSize = 100, + afterMemberId?: string, + lastGeneratedAt?: string, +): Promise { + try { + const queryBody: IMemberQueryBody = { + from: 0, + size: batchSize, + query: { + bool: { + filter: [ + { + term: { + uuid_tenantId: tenantId, + }, + }, + ], + }, + }, + sort: { + [`uuid_memberId`]: 'asc', + }, + collapse: { + field: 'uuid_memberId', + }, + _source: [ + 'uuid_memberId', + 'nested_identities', + 'uuid_arr_noMergeIds', + 'keyword_displayName', + 'string_arr_emails', + 'int_activityCount', + ], + } + + if (afterMemberId) { + queryBody.query.bool.filter.push({ + range: { + uuid_memberId: { + gt: afterMemberId, + }, + }, + }) + } + + if (lastGeneratedAt) { + queryBody.query.bool.filter.push({ + range: { + date_createdAt: { + gt: new Date(lastGeneratedAt).toISOString(), + }, + }, + }) + } + + const members: IMemberPartialAggregatesOpensearchRawResult[] = + ( + await svc.opensearch.client.search({ + index: OpenSearchIndex.MEMBERS, + body: queryBody, + }) + ).body?.hits?.hits || [] + + return members.map((member) => member._source) + } catch (err) { + throw new Error(err) + } +} diff --git a/services/apps/merge_suggestions_worker/src/main.ts b/services/apps/merge_suggestions_worker/src/main.ts new file mode 100644 index 0000000000..ca70e7405d --- /dev/null +++ b/services/apps/merge_suggestions_worker/src/main.ts @@ -0,0 +1,36 @@ +import { Config } from '@crowd/archetype-standard' +import { ServiceWorker, Options } from '@crowd/archetype-worker' + +import { scheduleGenerateMemberMergeSuggestions } from 'schedules/memberMergeSuggestions' + +const config: Config = { + envvars: [], + producer: { + enabled: false, + }, + temporal: { + enabled: true, + }, + redis: { + enabled: false, + }, +} + +const options: Options = { + postgres: { + enabled: true, + }, + opensearch: { + enabled: true, + }, +} + +export const svc = new ServiceWorker(config, options) + +setImmediate(async () => { + await svc.init() + + await scheduleGenerateMemberMergeSuggestions() + + await svc.start() +}) diff --git a/services/apps/merge_suggestions_worker/src/repo/memberMergeSuggestions.repo.ts b/services/apps/merge_suggestions_worker/src/repo/memberMergeSuggestions.repo.ts new file mode 100644 index 0000000000..d3e5544d66 --- /dev/null +++ b/services/apps/merge_suggestions_worker/src/repo/memberMergeSuggestions.repo.ts @@ -0,0 +1,192 @@ +import { DbConnection, DbTransaction } from '@crowd/database' +import { Logger } from '@crowd/logging' +import { IMemberMergeSuggestion } from '@crowd/types' +import { IMemberId, IMemberMergeSuggestionsLatestGeneratedAt, IMemberNoMerge } from 'types' +import { chunkArray, removeDuplicateSuggestions } from 'utils' + +class MemberMergeSuggestionsRepository { + constructor( + private readonly connection: DbConnection | DbTransaction, + private readonly log: Logger, + ) {} + + async findNoMergeIds(memberId: string): Promise { + try { + const results: IMemberNoMerge[] = await this.connection.any( + `select mnm."memberId", mnm."noMergeId" from "memberNoMerge" mnm + where mnm."memberId" = $(id) or mnm."noMergeId" = $(id);`, + { + id: memberId, + }, + ) + return Array.from( + results.reduce((acc, r) => { + if (memberId === r.memberId) { + acc.add(r.noMergeId) + } else if (memberId === r.noMergeId) { + acc.add(r.memberId) + } + return acc + }, new Set()), + ) + } catch (err) { + throw new Error(err) + } + } + + async findTenantsLatestMemberSuggestionGeneratedAt(tenantId: string): Promise { + try { + const result: IMemberMergeSuggestionsLatestGeneratedAt = await this.connection.oneOrNone( + ` + select "memberMergeSuggestionsLastGeneratedAt" + from tenants + where "id" = $(tenantId);`, + { + tenantId, + }, + ) + return result?.memberMergeSuggestionsLastGeneratedAt + } catch (err) { + throw new Error(err) + } + } + + async updateMemberMergeSuggestionsLastGeneratedAt(tenantId: string): Promise { + try { + await this.connection.any( + ` + update tenants set "memberMergeSuggestionsLastGeneratedAt" = now() + where "id" = $(tenantId); + `, + { + tenantId, + }, + ) + } catch (err) { + throw new Error(err) + } + } + + async addToMerge(suggestions: IMemberMergeSuggestion[]): Promise { + // Remove possible duplicates + suggestions = removeDuplicateSuggestions(suggestions) + + // check all suggestion ids exists in the db + const uniqueMemberIds = Array.from( + suggestions.reduce((acc, suggestion) => { + acc.add(suggestion.members[0]) + acc.add(suggestion.members[1]) + return acc + }, new Set()), + ) + + // filter non existing member ids from suggestions + const nonExistingIds = await this.findNonExistingIds(uniqueMemberIds) + + suggestions = suggestions.filter( + (s) => !nonExistingIds.includes(s.members[0]) && !nonExistingIds.includes(s.members[1]), + ) + + // Process suggestions in chunks of 100 or less + const suggestionChunks: IMemberMergeSuggestion[][] = chunkArray( + suggestions, + 100, + ) + + const insertValues = ( + memberId: string, + toMergeId: string, + similarity: number | null, + activityEstimate: number | null, + index: number, + ) => { + const idPlaceholder = (key: string) => `${key}${index}` + return { + query: `($(${idPlaceholder('memberId')})::uuid, $(${idPlaceholder( + 'toMergeId', + )})::uuid, $(${idPlaceholder('similarity')}), $(${idPlaceholder( + 'activityEstimate', + )})::integer, NOW(), NOW())`, + replacements: { + [idPlaceholder('memberId')]: memberId, + [idPlaceholder('toMergeId')]: toMergeId, + [idPlaceholder('similarity')]: similarity, + [idPlaceholder('activityEstimate')]: activityEstimate, + }, + } + } + + for (const suggestionChunk of suggestionChunks) { + const placeholders: string[] = [] + let replacements: Record = {} + + suggestionChunk.forEach((suggestion, index) => { + const { query, replacements: chunkReplacements } = insertValues( + suggestion.members[0], + suggestion.members[1], + suggestion.similarity, + suggestion.activityEstimate, + index, + ) + placeholders.push(query) + replacements = { ...replacements, ...chunkReplacements } + }) + + const query = ` + insert into "memberToMerge" ("memberId", "toMergeId", "similarity", "activityEstimate", "createdAt", "updatedAt") + select new_vals.* + from ( + values + ${placeholders.join(', ')} + ) AS new_vals ("memberId", "toMergeId", "similarity", "activityEstimate", "createdAt", "updatedAt") + where not exists ( + select 1 + from "memberToMerge" + where ("memberId" = new_vals."memberId"::uuid AND "toMergeId" = new_vals."toMergeId"::uuid) + or ("memberId" = new_vals."toMergeId"::uuid AND "toMergeId" = new_vals."memberId"::uuid) + ); + ` + try { + await this.connection.any(query, replacements) + } catch (error) { + this.log.error('Error adding members to merge', error) + throw error + } + } + } + + async findNonExistingIds(memberIds: string[]): Promise { + let idValues = `` + + for (let i = 0; i < memberIds.length; i++) { + idValues += `('${memberIds[i]}'::uuid)` + + if (i !== memberIds.length - 1) { + idValues += ',' + } + } + + const query = `WITH id_list (id) AS ( + VALUES + ${idValues} + ) + SELECT id + FROM id_list + WHERE NOT EXISTS ( + SELECT 1 + FROM members m + WHERE m.id = id_list.id + );` + + try { + const results: IMemberId[] = await this.connection.any(query) + + return results.map((r) => r.id) + } catch (error) { + this.log.error('Error while getting non existing members from db', error) + throw error + } + } +} + +export default MemberMergeSuggestionsRepository diff --git a/services/apps/merge_suggestions_worker/src/repo/tenant.repo.ts b/services/apps/merge_suggestions_worker/src/repo/tenant.repo.ts new file mode 100644 index 0000000000..8407daed98 --- /dev/null +++ b/services/apps/merge_suggestions_worker/src/repo/tenant.repo.ts @@ -0,0 +1,28 @@ +import { DbConnection, DbTransaction } from '@crowd/database' +import { Logger } from '@crowd/logging' +import { ITenant } from 'types' + +class TenantRepository { + constructor( + private readonly connection: DbConnection | DbTransaction, + private readonly log: Logger, + ) {} + + async getAllTenants(): Promise { + let rows: ITenant[] = [] + try { + rows = await this.connection.query(` + SELECT id as "tenantId", plan + FROM tenants WHERE "deletedAt" IS NULL; + `) + } catch (err) { + this.log.error('Error while getting all tenants', err) + + throw new Error(err) + } + + return rows + } +} + +export default TenantRepository diff --git a/services/apps/merge_suggestions_worker/src/schedules/memberMergeSuggestions.ts b/services/apps/merge_suggestions_worker/src/schedules/memberMergeSuggestions.ts new file mode 100644 index 0000000000..f750c6e29b --- /dev/null +++ b/services/apps/merge_suggestions_worker/src/schedules/memberMergeSuggestions.ts @@ -0,0 +1,42 @@ +import { ScheduleAlreadyRunning, ScheduleOverlapPolicy } from '@temporalio/client' + +import { svc } from '../main' +import { spawnSuggestionsForAllTenants } from 'workflows/spawnSuggestionsForAllTenants' +import { IS_DEV_ENV, IS_TEST_ENV } from '@crowd/common' + +export const scheduleGenerateMemberMergeSuggestions = async () => { + try { + await svc.temporal.schedule.create({ + scheduleId: 'member-merge-suggestions', + spec: + IS_DEV_ENV || IS_TEST_ENV + ? { + cronExpressions: ['*/2 * * * *'], + } + : { + intervals: [ + { + every: '2 hours', + }, + ], + }, + policies: { + overlap: ScheduleOverlapPolicy.BUFFER_ONE, + catchupWindow: '1 minute', + }, + action: { + type: 'startWorkflow', + workflowType: spawnSuggestionsForAllTenants, + taskQueue: 'merge-suggestions', + workflowExecutionTimeout: '5 minutes', + }, + }) + } catch (err) { + if (err instanceof ScheduleAlreadyRunning) { + svc.log.info('Schedule already registered in Temporal.') + svc.log.info('Configuration may have changed since. Please make sure they are in sync.') + } else { + throw new Error(err) + } + } +} diff --git a/services/apps/merge_suggestions_worker/src/types.ts b/services/apps/merge_suggestions_worker/src/types.ts new file mode 100644 index 0000000000..3b8a1fba71 --- /dev/null +++ b/services/apps/merge_suggestions_worker/src/types.ts @@ -0,0 +1,89 @@ +export interface ITenant { + tenantId: string + plan: string +} + +interface ITermFilter { + term: { + uuid_tenantId: string + } +} + +interface IRangeFilterMemberId { + range: { + uuid_memberId: { + gt: string + } + } +} + +interface IRangeFilterCreatedAt { + range: { + date_createdAt: { + gt: string + } + } +} + +export type IMemberFilter = ITermFilter | IRangeFilterMemberId | IRangeFilterCreatedAt + +export interface IMemberQueryBody { + from: number + size: number + query: { + bool: { + filter: IMemberFilter[] + } + } + sort: { + [key: string]: string + } + collapse: { + field: string + } + _source: string[] +} + +export interface IMemberIdentityOpensearch { + string_platform: string + string_username: string +} + +export interface IMemberPartialAggregatesOpensearch { + uuid_memberId: string + nested_identities: IMemberIdentityOpensearch[] + uuid_arr_noMergeIds: string[] + keyword_displayName: string + string_arr_emails: string[] + int_activityCount: number +} + +export interface IMemberPartialAggregatesOpensearchRawResult { + _source: IMemberPartialAggregatesOpensearch +} + +export interface ISimilarMember { + uuid_memberId: string + nested_identities: IMemberIdentityOpensearch[] + nested_weakIdentities: IMemberIdentityOpensearch[] + keyword_displayName: string + string_arr_emails: string[] + int_activityCount: number +} + +export interface ISimilarMemberOpensearch { + _source: ISimilarMember +} + +export interface IMemberNoMerge { + memberId: string + noMergeId: string +} + +export interface IMemberMergeSuggestionsLatestGeneratedAt { + memberMergeSuggestionsLastGeneratedAt: string +} + +export interface IMemberId { + id: string +} diff --git a/services/apps/merge_suggestions_worker/src/utils.ts b/services/apps/merge_suggestions_worker/src/utils.ts new file mode 100644 index 0000000000..6a22d51a7d --- /dev/null +++ b/services/apps/merge_suggestions_worker/src/utils.ts @@ -0,0 +1,107 @@ +import { IMemberMergeSuggestion } from '@crowd/types' +import { get as getLevenshteinDistance } from 'fast-levenshtein' + +import { + IMemberIdentityOpensearch, + IMemberPartialAggregatesOpensearch, + ISimilarMember, +} from 'types' + +export const prefixLength = (string: string) => { + if (string.length > 5 && string.length < 8) { + return 6 + } + + return 10 +} + +export const calculateSimilarity = ( + primaryMember: IMemberPartialAggregatesOpensearch, + similarMember: ISimilarMember, +): number => { + let smallestEditDistance: number = null + + let similarPrimaryIdentity: IMemberIdentityOpensearch = null + + // check displayName match + if ( + similarMember.keyword_displayName.toLowerCase() === + primaryMember.keyword_displayName.toLowerCase() + ) { + return 0.98 + } + + // check email match + if ( + similarMember.string_arr_emails && + similarMember.string_arr_emails.length > 0 && + similarMember.string_arr_emails.some((email) => primaryMember.string_arr_emails.includes(email)) + ) { + return 0.98 + } + + // find the smallest edit distance between both identity arrays + for (const primaryIdentity of primaryMember.nested_identities) { + // similar organization has a weakIdentity as one of primary organization's strong identity, return score 95 + if ( + similarMember.nested_weakIdentities && + similarMember.nested_weakIdentities.length > 0 && + similarMember.nested_weakIdentities.some( + (weakIdentity) => + weakIdentity.string_username === primaryIdentity.string_username && + weakIdentity.string_platform === primaryIdentity.string_platform, + ) + ) { + return 0.95 + } + + for (const secondaryIdentity of similarMember.nested_identities) { + const currentLevenstheinDistance = getLevenshteinDistance( + primaryIdentity.string_username, + secondaryIdentity.string_username, + ) + if (smallestEditDistance === null || smallestEditDistance > currentLevenstheinDistance) { + smallestEditDistance = currentLevenstheinDistance + similarPrimaryIdentity = primaryIdentity + } + } + } + + // calculate similarity percentage + const identityLength = similarPrimaryIdentity.string_username.length + + if (identityLength < smallestEditDistance) { + // if levensthein distance is bigger than the word itself, it might be a prefix match, return medium similarity + return (Math.floor(Math.random() * 21) + 20) / 100 + } + + return Math.floor(((identityLength - smallestEditDistance) / identityLength) * 100) / 100 +} + +export function removeDuplicateSuggestions( + suggestions: IMemberMergeSuggestion[], +): IMemberMergeSuggestion[] { + const seen = new Set() + + return suggestions.filter((suggestion) => { + // Sort members and convert them to string for comparison + const membersString = suggestion.members.slice().sort().join() + + if (seen.has(membersString)) { + // We have seen this pair of members before, filter it out + return false + } else { + // This is a new pair of members, add it to the set + seen.add(membersString) + return true + } + }) +} + +export function chunkArray(array: T[], chunkSize: number): T[][] { + const chunks = [] + for (let i = 0; i < array.length; i += chunkSize) { + chunks.push(array.slice(i, i + chunkSize)) + } + return chunks +} diff --git a/services/apps/merge_suggestions_worker/src/workflows.ts b/services/apps/merge_suggestions_worker/src/workflows.ts new file mode 100644 index 0000000000..84e0d59cc3 --- /dev/null +++ b/services/apps/merge_suggestions_worker/src/workflows.ts @@ -0,0 +1,5 @@ +import { generateMemberMergeSuggestions } from './workflows/generateMemberMergeSuggestions' + +import { spawnSuggestionsForAllTenants } from './workflows/spawnSuggestionsForAllTenants' + +export { generateMemberMergeSuggestions, spawnSuggestionsForAllTenants } diff --git a/services/apps/merge_suggestions_worker/src/workflows/generateMemberMergeSuggestions.ts b/services/apps/merge_suggestions_worker/src/workflows/generateMemberMergeSuggestions.ts new file mode 100644 index 0000000000..716b29f2f5 --- /dev/null +++ b/services/apps/merge_suggestions_worker/src/workflows/generateMemberMergeSuggestions.ts @@ -0,0 +1,55 @@ +import { proxyActivities, continueAsNew } from '@temporalio/workflow' +import * as activities from '../activities/member-merge-suggestions/getMergeSuggestions' + +import { IMemberMergeSuggestion, IProcessGenerateMemberMergeSuggestionsArgs } from '@crowd/types' +import { IMemberPartialAggregatesOpensearch } from 'types' +import { chunkArray } from '../utils' + +const activity = proxyActivities({ startToCloseTimeout: '1 minute' }) + +export async function generateMemberMergeSuggestions( + args: IProcessGenerateMemberMergeSuggestionsArgs, +): Promise { + const PAGE_SIZE = 1000 + const PARALLEL_SUGGESTION_PROCESSING = 250 + + let lastUuid: string = args.lastUuid || null + + // get the latest generation time of tenant's member suggestions, we'll only get members created after that for new suggestions + const lastGeneratedAt = await activity.findTenantsLatestMemberSuggestionGeneratedAt(args.tenantId) + + const result: IMemberPartialAggregatesOpensearch[] = await activity.getMembers( + args.tenantId, + PAGE_SIZE, + lastUuid, + lastGeneratedAt, + ) + + if (result.length === 0) { + await activity.updateMemberMergeSuggestionsLastGeneratedAt(args.tenantId) + return + } + + lastUuid = result.length > 0 ? result[result.length - 1]?.uuid_memberId : null + + const allMergeSuggestions: IMemberMergeSuggestion[] = [] + + const promiseChunks = chunkArray(result, PARALLEL_SUGGESTION_PROCESSING) + + for (const chunk of promiseChunks) { + const mergeSuggestionsPromises: Promise[] = chunk.map((member) => + activity.getMergeSuggestions(args.tenantId, member), + ) + + const mergeSuggestionsResults: IMemberMergeSuggestion[][] = + await Promise.all(mergeSuggestionsPromises) + allMergeSuggestions.push(...mergeSuggestionsResults.flat()) + } + + // Add all merge suggestions to add to merge + if (allMergeSuggestions.length > 0) { + await activity.addToMerge(allMergeSuggestions) + } + + await continueAsNew({ tenantId: args.tenantId, lastUuid }) +} diff --git a/services/apps/merge_suggestions_worker/src/workflows/spawnSuggestionsForAllTenants.ts b/services/apps/merge_suggestions_worker/src/workflows/spawnSuggestionsForAllTenants.ts new file mode 100644 index 0000000000..1465e46f6f --- /dev/null +++ b/services/apps/merge_suggestions_worker/src/workflows/spawnSuggestionsForAllTenants.ts @@ -0,0 +1,39 @@ +import { + proxyActivities, + startChild, + ParentClosePolicy, + ChildWorkflowCancellationType, + workflowInfo, +} from '@temporalio/workflow' + +import * as activities from '../activities/getAllTenants' +import { generateMemberMergeSuggestions } from './generateMemberMergeSuggestions' + +const activity = proxyActivities({ startToCloseTimeout: '1 minute' }) + +export async function spawnSuggestionsForAllTenants(): Promise { + const tenants = await activity.getAllTenants() + const info = workflowInfo() + await Promise.all( + tenants.map((tenant) => { + return startChild(generateMemberMergeSuggestions, { + workflowId: `${info.workflowId}/${tenant.tenantId}`, + cancellationType: ChildWorkflowCancellationType.ABANDON, + parentClosePolicy: ParentClosePolicy.PARENT_CLOSE_POLICY_ABANDON, + retry: { + backoffCoefficient: 2, + initialInterval: 2 * 1000, + maximumInterval: 30 * 1000, + }, + args: [ + { + tenantId: tenant.tenantId, + }, + ], + searchAttributes: { + TenantId: [tenant.tenantId], + }, + }) + }), + ) +} diff --git a/services/apps/merge_suggestions_worker/tsconfig.json b/services/apps/merge_suggestions_worker/tsconfig.json new file mode 100644 index 0000000000..e20e712429 --- /dev/null +++ b/services/apps/merge_suggestions_worker/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "target": "es2017", + "module": "Node16", + "lib": ["es6", "es7", "es2017", "es2017.object", "es2015.promise", "ES2021.String"], + "skipLibCheck": true, + "sourceMap": true, + "moduleResolution": "node16", + "experimentalDecorators": true, + "esModuleInterop": true, + "baseUrl": "./src", + "paths": { + "@crowd/*": ["../../../libs/*/src"], + "@crowd/archetype-*": ["../../../archetypes/*/src"] + } + }, + "include": ["src/**/*"] +} diff --git a/services/apps/premium/members_enrichment_worker/.eslintrc.cjs b/services/apps/premium/members_enrichment_worker/.eslintrc.cjs new file mode 100644 index 0000000000..25ba4e0d66 --- /dev/null +++ b/services/apps/premium/members_enrichment_worker/.eslintrc.cjs @@ -0,0 +1,21 @@ +module.exports = { + parser: '@typescript-eslint/parser', + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:prettier/recommended', + ], + plugins: ['@typescript-eslint', 'prettier'], + parserOptions: { + ecmaVersion: 2022, + sourceType: 'module', + }, + env: { + es6: true, + node: true, + }, + rules: { + 'prettier/prettier': 'error', + '@typescript-eslint/explicit-module-boundary-types': 'off', + }, +} diff --git a/services/apps/premium/members_enrichment_worker/.prettierignore b/services/apps/premium/members_enrichment_worker/.prettierignore new file mode 100644 index 0000000000..2b24877309 --- /dev/null +++ b/services/apps/premium/members_enrichment_worker/.prettierignore @@ -0,0 +1,3 @@ +dist/ +.eslintrc.cjs +.prettierrc.cjs diff --git a/services/apps/premium/members_enrichment_worker/.prettierrc.cjs b/services/apps/premium/members_enrichment_worker/.prettierrc.cjs new file mode 100644 index 0000000000..a8ca459839 --- /dev/null +++ b/services/apps/premium/members_enrichment_worker/.prettierrc.cjs @@ -0,0 +1,7 @@ +module.exports = { + singleQuote: true, + arrowParens: 'always', + printWidth: 100, + trailingComma: 'all', + semi: false, +} diff --git a/services/apps/premium/members_enrichment_worker/package.json b/services/apps/premium/members_enrichment_worker/package.json new file mode 100644 index 0000000000..472599552d --- /dev/null +++ b/services/apps/premium/members_enrichment_worker/package.json @@ -0,0 +1,43 @@ +{ + "name": "@crowd/members-enrichment-worker", + "version": "1.0.0", + "private": true, + "scripts": { + "start": "CROWD_TEMPORAL_TASKQUEUE=members-enrichment SERVICE=members-enrichment-worker TS_NODE_TRANSPILE_ONLY=true node -r tsconfig-paths/register -r ts-node/register src/main.ts", + "start:debug:local": "set -a && . ../../../../backend/.env.dist.local && . ../../../../backend/.env.override.local && set +a && CROWD_TEMPORAL_TASKQUEUE=members-enrichment SERVICE=members-enrichment-worker TS_NODE_TRANSPILE_ONLY=true LOG_LEVEL=trace node --inspect=0.0.0.0:9232 -r tsconfig-paths/register -r ts-node/register src/main.ts", + "start:debug": "CROWD_TEMPORAL_TASKQUEUE=members-enrichment SERVICE=members-enrichment-worker TS_NODE_TRANSPILE_ONLY=true LOG_LEVEL=trace node --inspect=0.0.0.0:9232 -r tsconfig-paths/register -r ts-node/register src/main.ts", + "dev:local": "./node_modules/.bin/nodemon --watch src --watch ../../../libs --ext ts --exec pnpm run start:debug:local", + "dev": "./node_modules/.bin/nodemon --watch src --watch ../../../libs --ext ts --exec pnpm run start:debug", + "lint": "./node_modules/.bin/eslint --ext .ts src --max-warnings=0", + "format": "./node_modules/.bin/prettier --write \"src/**/*.ts\"", + "format-check": "./node_modules/.bin/prettier --check .", + "tsc-check": "./node_modules/.bin/tsc --noEmit" + }, + "dependencies": { + "@crowd/archetype-standard": "file:../../../archetypes/standard", + "@crowd/archetype-worker": "file:../../../archetypes/worker", + "@crowd/common": "file:../../../libs/common", + "@crowd/opensearch": "file:../../../libs/opensearch", + "@crowd/types": "file:../../../libs/types", + "@temporalio/activity": "~1.8.6", + "@temporalio/client": "~1.8.6", + "@temporalio/workflow": "~1.8.6", + "axios": "~1.6.2", + "lodash": "~4.17.21", + "moment": "~2.29.4", + "ts-node": "^10.9.1", + "tsconfig-paths": "^4.2.0", + "typescript": "^5.2.2" + }, + "devDependencies": { + "@types/node": "^20.8.2", + "@types/uuid": "~9.0.6", + "@typescript-eslint/eslint-plugin": "^6.7.4", + "@typescript-eslint/parser": "^6.7.4", + "eslint": "^8.50.0", + "eslint-config-prettier": "^9.0.0", + "eslint-plugin-prettier": "^5.0.0", + "nodemon": "^3.0.1", + "prettier": "^3.0.3" + } +} diff --git a/services/apps/premium/members_enrichment_worker/src/activities.ts b/services/apps/premium/members_enrichment_worker/src/activities.ts new file mode 100644 index 0000000000..e29c0505e7 --- /dev/null +++ b/services/apps/premium/members_enrichment_worker/src/activities.ts @@ -0,0 +1,25 @@ +import { getMembers } from './activities/getMembers' +import { + enrichMemberUsingGitHubHandle, + enrichMemberUsingEmailAddress, +} from './activities/getEnrichmentData' +import { + normalizeEnrichedMember, + updateMergeSuggestions, + updateOrganizations, +} from './activities/normalizeEnrichedMember' +import { + syncMembersToOpensearch, + syncOrganizationsToOpensearch, +} from './activities/syncEnrichedData' + +export { + getMembers, + enrichMemberUsingGitHubHandle, + enrichMemberUsingEmailAddress, + normalizeEnrichedMember, + updateMergeSuggestions, + updateOrganizations, + syncMembersToOpensearch, + syncOrganizationsToOpensearch, +} diff --git a/services/apps/premium/members_enrichment_worker/src/activities/getEnrichmentData.ts b/services/apps/premium/members_enrichment_worker/src/activities/getEnrichmentData.ts new file mode 100644 index 0000000000..3de1dbc52a --- /dev/null +++ b/services/apps/premium/members_enrichment_worker/src/activities/getEnrichmentData.ts @@ -0,0 +1,78 @@ +import axios, { AxiosResponse } from 'axios' + +import { PlatformType } from '@crowd/types' +import { EnrichmentAPIResponse, EnrichmentAPIMember } from '@crowd/types/premium' + +import { EnrichingMember } from '../types/enrichment' + +/* +enrichMemberUsingGitHubHandle is a Temporal activity that fetches enrichment data +from external API using the member's GitHub username. +*/ +export async function enrichMemberUsingGitHubHandle( + input: EnrichingMember, +): Promise { + const url = `${process.env['CROWD_ENRICHMENT_URL']}/get_profile` + + let response: AxiosResponse = null + try { + response = await axios({ + method: 'get', + url, + params: { + github_handle: input.member.username[PlatformType.GITHUB], + with_emails: true, + api_key: process.env['CROWD_ENRICHMENT_API_KEY'], + }, + headers: {}, + }) + } catch (err) { + if (!response || response.status === 500) { + return null + } + + throw new Error(err) + } + + if (!response.data.profile) { + return null + } + + return response.data.profile +} + +/* +enrichMemberUsingEmailAddress is a Temporal activity that fetches enrichment data +from external API using the member's email address. +*/ +export async function enrichMemberUsingEmailAddress( + input: EnrichingMember, +): Promise { + const url = `${process.env['CROWD_ENRICHMENT_URL']}/get_profile` + + let response: AxiosResponse = null + try { + response = await axios({ + method: 'get', + url, + params: { + email: input.member.emails[0], + with_emails: true, + api_key: process.env['CROWD_ENRICHMENT_API_KEY'], + }, + headers: {}, + }) + } catch (err) { + if (!response || response.status === 500) { + return null + } + + throw new Error(err) + } + + if (!response.data.profile) { + return null + } + + return response.data.profile +} diff --git a/services/apps/premium/members_enrichment_worker/src/activities/getMembers.ts b/services/apps/premium/members_enrichment_worker/src/activities/getMembers.ts new file mode 100644 index 0000000000..b0da58c2d1 --- /dev/null +++ b/services/apps/premium/members_enrichment_worker/src/activities/getMembers.ts @@ -0,0 +1,52 @@ +import { IMember } from '@crowd/types' + +import { svc } from '../main' + +/* +getMembers is a Temporal activity that retrieves all members available for +enrichment. Member must have one of GitHub username or email address, must not +have been enriched in the past 90 days, and must be part of tenant with a plan +allowing this feature. We limit to 10 members per workflow to not overload +OpenSearch and external APIs, but mostly to not exceed Temporal result size limit. +*/ +export async function getMembers(): Promise { + let rows: IMember[] = [] + + try { + rows = await svc.postgres.reader.connection().query( + `SELECT + members."id", + members."displayName", + members."attributes", + members."emails", + members."contributions", + members."score", + members."reach", + members."tenantId", + jsonb_object_agg(mi.platform, mi.username) as username, + COUNT(activities."memberId") AS activity_count + FROM members + INNER JOIN tenants ON tenants.id = members."tenantId" + INNER JOIN "memberIdentities" mi ON mi."memberId" = members.id + INNER JOIN activities ON activities."memberId" = members.id + WHERE tenants.plan IN ('Growth', 'Scale', 'Enterprise') + AND ( + members."lastEnriched" < NOW() - INTERVAL '90 days' + OR members."lastEnriched" IS NULL + ) + AND ( + mi.platform = 'github' + OR array_length(members.emails, 1) > 0 + ) + AND tenants."deletedAt" IS NULL + AND members."deletedAt" IS NULL + GROUP BY members.id + ORDER BY activity_count DESC + LIMIT 10;`, + ) + } catch (err) { + throw new Error(err) + } + + return rows +} diff --git a/services/apps/premium/members_enrichment_worker/src/activities/normalizeEnrichedMember.ts b/services/apps/premium/members_enrichment_worker/src/activities/normalizeEnrichedMember.ts new file mode 100644 index 0000000000..6fbcacb90c --- /dev/null +++ b/services/apps/premium/members_enrichment_worker/src/activities/normalizeEnrichedMember.ts @@ -0,0 +1,290 @@ +import moment from 'moment' + +import { generateUUIDv4 } from '@crowd/common' +import { IMember, IOrganizationIdentity, OrganizationSource, PlatformType } from '@crowd/types' + +import { svc } from '../main' +import { normalize } from '../utils/normalize' +import { EnrichingMember } from '../types/enrichment' + +/* +normalizeEnrichedMember is a Temporal activity that, given a member and enriched +data received, normalizes and updates all the member's fields/attributes in the +database. +*/ +export async function normalizeEnrichedMember(input: EnrichingMember): Promise { + let member: IMember + + try { + await svc.postgres.writer.connection().tx(async (tx) => { + try { + member = await normalize(tx, input.member, input.enrichment) + } catch (err) { + throw new Error(err) + } + }) + } catch (err) { + throw new Error(err) + } + + return member +} + +/* +updateMergeSuggestions is a Temporal activity that update member merge suggestions +in the database for a member and enriched data received. +*/ +export async function updateMergeSuggestions(input: EnrichingMember): Promise { + if (input.member.username) { + try { + await svc.postgres.writer.connection().tx(async (tx) => { + const filteredUsername = Object.keys(input.member.username).reduce((obj, key) => { + if (!input.member.username[key]) { + obj[key] = input.member.username[key] + } + return obj + }, {}) + + for (const [platform, usernames] of Object.entries(filteredUsername)) { + const usernameArray = Array.isArray(usernames) ? usernames : [usernames] + + for (const username of usernameArray) { + const usernames: string[] = [] + if (typeof username === 'string') { + usernames.push(username) + } else if (typeof username === 'object') { + if ('username' in username) { + usernames.push(username.username) + } else if (platform in username) { + if (typeof username[platform] === 'string') { + usernames.push(username[platform]) + } else if (Array.isArray(username[platform])) { + if (username[platform].length === 0) { + return input.member + } else if (typeof username[platform] === 'string') { + usernames.push(...username[platform]) + } else if (typeof username[platform][0] === 'object') { + usernames.push(...username[platform].map((u) => u.username)) + } + } else if (typeof username[platform] === 'object') { + usernames.push(username[platform].username) + } else { + return input.member + } + } else { + return input.member + } + } + + // Check if a member with this username already exists. + const existingMember = await svc.postgres.reader.connection().query( + `SELECT mi."memberId" + FROM "memberIdentities" mi + WHERE mi."tenantId" = $1 AND + mi.platform = $2 AND + mi.username in ($3) AND + EXISTS (SELECT 1 FROM "memberSegments" ms WHERE ms."memberId" = mi."memberId")`, + [input.member.tenantId, platform, usernames], + ) + + // Add the member to merge suggestions. + if (existingMember) { + await tx.query( + `INSERT INTO "memberToMerge" ("memberId", "toMergeId", similarity) + VALUES ($1, $2, $3);"`, + [input.member.id, existingMember.id, 0.9], + ) + + // Filter out the identity that belongs to another member from the normalized payload + if (Array.isArray(input.member.username[platform])) { + input.member.username[platform] = input.member.username[platform].filter( + (u) => u !== username, + ) + } else if (typeof input.member.username[platform] === 'string') { + delete input.member.username[platform] + } else { + throw new Error( + `Unsupported data type for input.member.username[platform] "${input.member.username[platform]}".`, + ) + } + } + } + } + }) + } catch (err) { + throw new Error(err) + } + } + + return input.member +} + +/* +updateOrganizations is a Temporal activity that update organizations in the +database thanks to enriched data received: + - upsert organization + - upsert `memberOrganization` relation +*/ +export async function updateOrganizations(input: EnrichingMember): Promise { + const organizations: string[] = [] + if (input.enrichment.work_experiences) { + try { + await svc.postgres.writer.connection().tx(async (tx) => { + for (const workExperience of input.enrichment.work_experiences) { + // Find the organization id. We first try to retrieve it, or we then try + // to upsert it. We first need a select to find occurence via displayed + // name. + let orgId: string + const existing = await svc.postgres.reader.connection().query( + `SELECT id FROM organizations + WHERE "displayName" ILIKE $1 + AND "tenantId" = $2 + AND "deletedAt" IS NULL;`, + [workExperience.company, input.member.tenantId], + ) + + if (existing && existing[0]) { + orgId = existing[0].id + } else { + orgId = generateUUIDv4() + + const upserted = await tx.query( + `INSERT INTO organizations (id, "tenantId", "displayName", website, linkedin, location, "createdAt", "updatedAt") + VALUES ($1, $2, $3, $4, $5, $6, NOW(), NOW()) + ON CONFLICT (website, "tenantId") + WHERE website IS NOT NULL + DO UPDATE SET + linkedin = EXCLUDED.linkedin, + location = EXCLUDED.location, + "updatedAt" = NOW() + RETURNING id;`, + [ + orgId, + input.member.tenantId, + workExperience.company, + workExperience.companyUrl, + workExperience.companyLinkedInUrl + ? { + url: workExperience.companyLinkedInUrl, + handle: workExperience.companyLinkedInUrl.split('/').pop(), + } + : null, + workExperience.location, + ], + ) + + if (upserted) { + orgId = upserted[0].id + } + } + + organizations.push(orgId) + + const organizationIdentities: IOrganizationIdentity[] = [ + { + name: workExperience.company, + platform: PlatformType.ENRICHMENT, + }, + ] + + if (workExperience.companyLinkedInUrl) { + const name = workExperience.companyLinkedInUrl.split('/').pop() + if (name) { + organizationIdentities.push({ + name: name, + platform: PlatformType.LINKEDIN, + url: workExperience.companyLinkedInUrl, + }) + } + } + + for (const orgIdentity of organizationIdentities) { + await tx.query( + `INSERT INTO "organizationIdentities" ("organizationId", "tenantId", name, platform, url) + VALUES ($1, $2, $3, $4, $5) + ON CONFLICT ON CONSTRAINT "organizationIdentities_platform_name_tenantId_key" + DO UPDATE SET name = EXCLUDED.name, url = EXCLUDED.url;`, + [ + orgId, + input.member.tenantId, + orgIdentity.name, + orgIdentity.platform, + orgIdentity.url, + ], + ) + } + + const dateEnd = workExperience.endDate + ? moment.utc(workExperience.endDate).toISOString() + : null + + const data = { + memberId: input.member.id, + organizationId: orgId, + title: workExperience.title, + dateStart: workExperience.startDate, + dateEnd, + source: OrganizationSource.ENRICHMENT, + } + + // Clean up organizations without dates if we're getting ones with dates. + if (data.dateStart) { + await tx.query( + `UPDATE "memberOrganizations" + SET "deletedAt" = NOW() + WHERE "memberId" = $1 + AND "organizationId" = $2 + AND "dateStart" IS NULL + AND "dateEnd" IS NULL + `, + [input.member.id, orgId], + ) + } else { + const rows = await svc.postgres.reader.connection().query( + `SELECT COUNT(*) AS count FROM "memberOrganizations" + WHERE "memberId" = $1 + AND "organizationId" = $2 + AND "dateStart" IS NOT NULL + AND "deletedAt" IS NULL + `, + [input.member.id, orgId], + ) + const row = rows[0] + + // If we're getting organization without dates, but there's already + // one with dates, don't insert + if (row.count > 0) { + return + } + } + + let conflictCondition = `("memberId", "organizationId", "dateStart", "dateEnd")` + if (!dateEnd) { + conflictCondition = `("memberId", "organizationId", "dateStart") WHERE "dateEnd" IS NULL` + } + if (!data.dateStart) { + conflictCondition = `("memberId", "organizationId") WHERE "dateStart" IS NULL AND "dateEnd" IS NULL` + } + + const onConflict = + data.source === OrganizationSource.UI + ? `ON CONFLICT ${conflictCondition} DO UPDATE SET "title" = $3, "dateStart" = $4, "dateEnd" = $5, "deletedAt" = NULL, "source" = $6` + : 'ON CONFLICT DO NOTHING' + + await tx.query( + ` + INSERT INTO "memberOrganizations" ("memberId", "organizationId", "createdAt", "updatedAt", "title", "dateStart", "dateEnd", "source") + VALUES ($1, $2, NOW(), NOW(), $3, $4, $5, $6) + ${onConflict}; + `, + [input.member.id, orgId, data.title, data.dateStart, data.dateEnd, data.source], + ) + } + }) + } catch (err) { + throw new Error(err) + } + } + + return organizations +} diff --git a/services/apps/premium/members_enrichment_worker/src/activities/syncEnrichedData.ts b/services/apps/premium/members_enrichment_worker/src/activities/syncEnrichedData.ts new file mode 100644 index 0000000000..47c7156f21 --- /dev/null +++ b/services/apps/premium/members_enrichment_worker/src/activities/syncEnrichedData.ts @@ -0,0 +1,44 @@ +import { MemberSyncService, OrganizationSyncService } from '@crowd/opensearch' + +import { svc } from '../main' + +const syncMembers = new MemberSyncService(svc.redis, svc.postgres.writer, svc.opensearch, svc.log, { + edition: process.env['CROWD_EDITION'], +}) + +const syncOrganizations = new OrganizationSyncService( + svc.postgres.writer, + svc.opensearch, + svc.log, + { + edition: process.env['CROWD_EDITION'], + }, +) + +/* +syncMembersToOpensearch is a Temporal activity that sync a newly enriched member +in database to OpenSearch. +*/ +export async function syncMembersToOpensearch(input: string[]): Promise { + try { + await syncMembers.syncMembers(input) + } catch (err) { + throw new Error(err) + } + + return null +} + +/* +syncOrganizationsToOpensearch is a Temporal activity that sync newly enriched +organizations in database to OpenSearch. +*/ +export async function syncOrganizationsToOpensearch(input: string[]): Promise { + try { + await syncOrganizations.syncOrganizations(input) + } catch (err) { + throw new Error(err) + } + + return null +} diff --git a/services/apps/premium/members_enrichment_worker/src/main.ts b/services/apps/premium/members_enrichment_worker/src/main.ts new file mode 100644 index 0000000000..0b017113d7 --- /dev/null +++ b/services/apps/premium/members_enrichment_worker/src/main.ts @@ -0,0 +1,35 @@ +import { Config } from '@crowd/archetype-standard' +import { ServiceWorker, Options } from '@crowd/archetype-worker' + +import { scheduleMembersEnrichment } from './schedules' + +const config: Config = { + producer: { + enabled: false, + }, + temporal: { + enabled: true, + }, + redis: { + enabled: true, + }, +} + +const options: Options = { + postgres: { + enabled: true, + }, + opensearch: { + enabled: true, + }, +} + +export const svc = new ServiceWorker(config, options) + +setImmediate(async () => { + await svc.init() + + await scheduleMembersEnrichment() + + await svc.start() +}) diff --git a/services/apps/premium/members_enrichment_worker/src/schedules.ts b/services/apps/premium/members_enrichment_worker/src/schedules.ts new file mode 100644 index 0000000000..5846f322a4 --- /dev/null +++ b/services/apps/premium/members_enrichment_worker/src/schedules.ts @@ -0,0 +1,3 @@ +import { scheduleMembersEnrichment } from './schedules/getMembersToEnrich' + +export { scheduleMembersEnrichment } diff --git a/services/apps/premium/members_enrichment_worker/src/schedules/getMembersToEnrich.ts b/services/apps/premium/members_enrichment_worker/src/schedules/getMembersToEnrich.ts new file mode 100644 index 0000000000..951eb826a8 --- /dev/null +++ b/services/apps/premium/members_enrichment_worker/src/schedules/getMembersToEnrich.ts @@ -0,0 +1,33 @@ +import { ScheduleAlreadyRunning, ScheduleOverlapPolicy } from '@temporalio/client' + +import { svc } from '../main' +import { getMembersToEnrich } from '../workflows' +import { IS_DEV_ENV, IS_TEST_ENV } from '@crowd/common' + +export const scheduleMembersEnrichment = async () => { + try { + await svc.temporal.schedule.create({ + scheduleId: 'members-enrichment', + spec: { + cronExpressions: IS_DEV_ENV || IS_TEST_ENV ? ['*/2 * * * *'] : ['*/30 * * * *'], + }, + policies: { + overlap: ScheduleOverlapPolicy.BUFFER_ONE, + catchupWindow: '1 minute', + }, + action: { + type: 'startWorkflow', + workflowType: getMembersToEnrich, + taskQueue: 'members-enrichment', + workflowExecutionTimeout: '5 minutes', + }, + }) + } catch (err) { + if (err instanceof ScheduleAlreadyRunning) { + svc.log.info('Schedule already registered in Temporal.') + svc.log.info('Configuration may have changed since. Please make sure they are in sync.') + } else { + throw new Error(err) + } + } +} diff --git a/services/apps/premium/members_enrichment_worker/src/types/enrichment.ts b/services/apps/premium/members_enrichment_worker/src/types/enrichment.ts new file mode 100644 index 0000000000..c957ee3de8 --- /dev/null +++ b/services/apps/premium/members_enrichment_worker/src/types/enrichment.ts @@ -0,0 +1,7 @@ +import { IMember } from '@crowd/types' +import { EnrichmentAPIMember } from '@crowd/types/premium' + +export interface EnrichingMember { + member: IMember + enrichment?: EnrichmentAPIMember +} diff --git a/services/apps/premium/members_enrichment_worker/src/utils/normalize.ts b/services/apps/premium/members_enrichment_worker/src/utils/normalize.ts new file mode 100644 index 0000000000..cebb39db8f --- /dev/null +++ b/services/apps/premium/members_enrichment_worker/src/utils/normalize.ts @@ -0,0 +1,495 @@ +import lodash from 'lodash' + +import { + MemberAttributeType, + MemberEnrichmentAttributes, + MemberAttributes, + MemberAttributeName, + MemberEnrichmentAttributeName, + PlatformType, + IMember, +} from '@crowd/types' +import { + EnrichmentAPIContribution, + EnrichmentAPISkills, + EnrichmentAPIMember, + EnrichmentAPIWorkExperience, + EnrichmentAPIEducation, + EnrichmentAPICertification, +} from '@crowd/types/premium' +import { DbTransaction } from '@crowd/database' +import { generateUUIDv4 } from '@crowd/common' + +const priorities: string[] = [ + 'custom', + 'twitter', + 'github', + 'linkedin', + 'reddit', + 'devto', + 'hackernews', + 'slack', + 'discord', + 'enrichment', + 'crowd', +] + +const attributeSettings = { + [MemberAttributeName.AVATAR_URL]: { + fields: ['profile_pic_url'], + default: true, + }, + [MemberAttributeName.LOCATION]: { + fields: ['location'], + default: true, + }, + [MemberAttributeName.BIO]: { + fields: ['title', 'work_experiences[0].title'], + }, + [MemberEnrichmentAttributeName.SENIORITY_LEVEL]: { + fields: ['seniority_level'], + type: MemberAttributeType.STRING, + }, + [MemberEnrichmentAttributeName.COUNTRY]: { + fields: ['country'], + type: MemberAttributeType.STRING, + }, + [MemberEnrichmentAttributeName.PROGRAMMING_LANGUAGES]: { + fields: ['programming_languages'], + type: MemberAttributeType.MULTI_SELECT, + }, + [MemberEnrichmentAttributeName.LANGUAGES]: { + fields: ['languages'], + type: MemberAttributeType.MULTI_SELECT, + }, + [MemberEnrichmentAttributeName.YEARS_OF_EXPERIENCE]: { + fields: ['years_of_experience'], + type: MemberAttributeType.NUMBER, + }, + [MemberEnrichmentAttributeName.EXPERTISE]: { + fields: ['expertise'], + type: MemberAttributeType.MULTI_SELECT, + }, + [MemberEnrichmentAttributeName.WORK_EXPERIENCES]: { + fields: ['work_experiences'], + type: MemberAttributeType.SPECIAL, + fn: (workExperiences: EnrichmentAPIWorkExperience[]) => + workExperiences.map((workExperience) => { + const { title, company, location, startDate, endDate } = workExperience + return { + title, + company, + location, + startDate, + endDate: endDate || 'Present', + } + }), + }, + [MemberEnrichmentAttributeName.EDUCATION]: { + fields: ['educations'], + type: MemberAttributeType.SPECIAL, + fn: (educations: EnrichmentAPIEducation[]) => + educations.map((education) => { + const { campus, major, specialization, startDate, endDate } = education + return { + campus, + major, + specialization, + startDate, + endDate: endDate || 'Present', + } + }), + }, + [MemberEnrichmentAttributeName.AWARDS]: { + fields: ['awards'], + type: MemberAttributeType.SPECIAL, + }, + [MemberEnrichmentAttributeName.CERTIFICATIONS]: { + fields: ['certifications'], + type: MemberAttributeType.SPECIAL, + fn: (certifications: EnrichmentAPICertification[]) => + certifications.map((certification) => { + const { title, description } = certification + return { + title, + description, + } + }), + }, +} + +export const normalize = async ( + tx: DbTransaction, + member: IMember, + enriched: EnrichmentAPIMember, +): Promise => { + if (enriched === null) { + try { + await tx.query( + `UPDATE members SET "lastEnriched" = NOW(), "updatedAt" = NOW() WHERE id = $1 AND "tenantId" = $2;`, + [member.id, member.tenantId], + ) + } catch (err) { + throw new Error(err) + } + + return member + } + + try { + member = await fillAttributes(tx, member, enriched) + } catch (err) { + throw new Error(err) + } + + try { + member = await fillSkills(tx, member, enriched) + } catch (err) { + throw new Error(err) + } + + try { + member = await fillPlatformData(tx, member, enriched) + } catch (err) { + throw new Error(err) + } + + return member +} + +/** + * This function is used to fill in a member's social media handles and profile links based on data obtained from an external API + * @param member - The object that contains properties such as 'username' and 'attributes' + * @param enriched - An object that contains data obtained from an external API + * @returns the updated 'member' object + */ +// eslint-disable-next-line class-methods-use-this +const fillPlatformData = async ( + tx: DbTransaction, + member: IMember, + enriched: EnrichmentAPIMember, +): Promise => { + // NOTE: Enrichment API returns a list of email address not associated to the + // actual member. We simply ignore these for now. + // if (enriched.emails && Array.isArray(enriched.emails)) { + // if (enriched.emails.length > 0) { + // const emailSet = new Set( + // enriched.emails.filter((email) => !email.includes('noreply.github')), + // ) + + // member.emails.forEach((email) => emailSet.add(email)) + // member.emails = Array.from(emailSet) + // } + // } + + if (!member.emails) { + member.emails = [] + } + + member.contributions = enriched.oss_contributions?.map( + (contribution: EnrichmentAPIContribution) => ({ + id: contribution.id, + topics: contribution.topics, + summary: contribution.summary, + url: contribution.github_url, + firstCommitDate: contribution.first_commit_date, + lastCommitDate: contribution.last_commit_date, + numberCommits: contribution.num_of_commits, + }), + ) + + if (enriched.github_handle) { + // Set 'member.username.github' to be equal to 'enriched.github_handle' (if it is not already set) + member.username[PlatformType.GITHUB] = + member.username[PlatformType.GITHUB] || enriched.github_handle + if (!member.attributes.url) { + // If it does not exist, initialize it as an empty object + member.attributes.url = {} + } + // Set 'member.attributes.url.github' to be equal to a string concatenated with the 'github_handle' property + member.attributes.url.github = + member.attributes.url.github || `https://github.com/${enriched.github_handle}` + } + + if (enriched.linkedin_url) { + member.username[PlatformType.LINKEDIN] = + member.username[PlatformType.LINKEDIN] || enriched.linkedin_url.split('/').pop() + + if (!member.attributes.url) { + member.attributes.url = {} + } + + member.attributes.url.linkedin = member.attributes.url.linkedin || enriched.linkedin_url + } + + if (enriched.twitter_handle) { + member.username[PlatformType.TWITTER] = + member.username[PlatformType.TWITTER] || enriched.twitter_handle + + if (!member.attributes.url) { + member.attributes.url = {} + } + member.attributes.url.twitter = + member.attributes.url.twitter || `https://twitter.com/${enriched.twitter_handle}` + } + + // We are updating the displayName only if the existing one has one word only + // And we are using an update here instead of the upsert because + // upsert always takes the existing displayName + let stmtDisplayName = '' + if (!/\W/.test(member.displayName)) { + if (enriched.first_name && enriched.last_name) { + member.displayName = `${enriched.first_name} ${enriched.last_name}` + stmtDisplayName = `"displayName" = $1,` + } + } + + try { + await tx.query( + `UPDATE members SET ${stmtDisplayName} + emails = $2, + attributes = $3, + contributions = $4, + "lastEnriched" = NOW(), + "updatedAt" = NOW() + WHERE id = $5 AND "tenantId" = $6;`, + [ + member.displayName, + member.emails, + member.attributes, + JSON.stringify(member.contributions), + member.id, + member.tenantId, + ], + ) + } catch (err) { + throw new Error(err) + } + + for (const platform in member.username) { + try { + await tx.query( + `INSERT INTO "memberIdentities" ("memberId", "tenantId", platform, username) + VALUES ($1, $2, $3, $4) + ON CONFLICT ON CONSTRAINT "memberIdentities_platform_username_tenantId_key" DO UPDATE + SET username = EXCLUDED.username, "updatedAt" = NOW();`, + [member.id, member.tenantId, platform, member.username[platform]], + ) + } catch (err) { + throw new Error(err) + } + } + + try { + await tx.query( + `INSERT INTO "memberEnrichmentCache" ("memberId", "data", "createdAt", "updatedAt") + VALUES ($1, $2, NOW(), NOW()) + ON CONFLICT ("memberId") DO UPDATE + SET data = EXCLUDED.data, "updatedAt" = NOW();`, + [member.id, JSON.stringify(enriched)], + ) + } catch (err) { + throw new Error(err) + } + + return member +} + +/** + * This function is used to fill in a member's attributes based on data obtained from an external API + * @param member - The object that contains properties such as 'attributes' + * @param enriched - An object that contains data obtained from an external API + * @returns the updated 'member' object + */ +const fillAttributes = async ( + tx: DbTransaction, + member: IMember, + enriched: EnrichmentAPIMember, +): Promise => { + // Check if 'member.attributes' property exists + if (!member.attributes) { + // If it does not exist, initialize it as an empty object + member.attributes = {} + } + + // eslint-disable-next-line guard-for-in + for (const attributeName in attributeSettings) { + const attribute = attributeSettings[attributeName] + + let value = null + + for (const field of attribute.fields) { + if (value) { + break + } + // Get value from 'enriched' object using the defined mapping and 'lodash.get' + value = lodash.get(enriched, field) + } + + if (value) { + // Check if 'member.attributes[attributeName]' exists, and if it does not, initialize it as an empty object + if (!member.attributes[attributeName]) { + member.attributes[attributeName] = {} + } + + // Check if 'attribute.fn' exists, otherwise set it the identity function + const fn = attribute.fn || ((value) => value) + value = fn(value) + + // Assign 'value' to 'member.attributes[attributeName].enrichment' + // Then, apply the attribute in 'default' key, following the priority. + member.attributes[attributeName].enrichment = value + for (const platform of priorities) { + if (member.attributes[attributeName][platform]) { + member.attributes[attributeName]['default'] = value + break + } + } + + try { + await createAttributeAndUpdateOptions(tx, member, attributeName, attribute, value) + } catch (err) { + throw new Error(err) + } + } + } + + return member +} + +/** + * This function is used to fill in a member's skills based on data obtained from an external API + * @param member - The object that contains properties such as 'attributes' + * @param enriched - An object that contains data obtained from an external API + * @returns the updated 'member' object + */ +const fillSkills = async ( + tx: DbTransaction, + member: IMember, + enriched: EnrichmentAPIMember, +): Promise => { + // Check if 'enriched.skills' properties exists + if (enriched.skills) { + if (!member.attributes.skills) { + member.attributes.skills = {} + } + + // Assign unique and ordered skills to 'member.attributes[MemberEnrichmentAttributeName.SKILLS].enrichment' + member.attributes[MemberEnrichmentAttributeName.SKILLS].enrichment = lodash.uniq([ + // Use 'lodash.orderBy' to sort the skills by weight in descending order + ...lodash + .orderBy(enriched.skills || [], ['weight'], ['desc']) + .map((s: EnrichmentAPISkills) => s.skill), + ]) + + // Assign 'value' to 'member.attributes['skills'].enrichment' + // Then, apply the attribute in 'default' key, following the priority. + for (const platform of priorities) { + if (member.attributes[MemberEnrichmentAttributeName.SKILLS][platform]) { + member.attributes[MemberEnrichmentAttributeName.SKILLS]['default'] = lodash.uniq([ + // Use 'lodash.orderBy' to sort the skills by weight in descending order + ...lodash + .orderBy(enriched.skills || [], ['weight'], ['desc']) + .map((s: EnrichmentAPISkills) => s.skill), + ]) + break + } + } + + try { + await createAttributeAndUpdateOptions( + tx, + member, + MemberEnrichmentAttributeName.SKILLS, + { type: MemberAttributeType.MULTI_SELECT }, + member.attributes.skills.enrichment, + ) + } catch (err) { + throw new Error(err) + } + } + + return member +} + +/** + * This function is used to create new attribute and update options for member's attributes + * @param attributeName - The name of the attribute + * @param attribute - The attribute object + * @param value - the value of the attribute + */ +const createAttributeAndUpdateOptions = async ( + tx: DbTransaction, + member: IMember, + attributeName, + attribute, + value, +): Promise => { + // Check if attribute type is 'MULTI_SELECT' and the attribute already exists + if (attribute.type === MemberAttributeType.MULTI_SELECT && member.attributes[attributeName]) { + for (const option of value) { + try { + await tx.query( + `UPDATE "memberAttributeSettings" + SET options = array_append(options, $1), "updatedAt" = NOW() + WHERE name = $2 AND "tenantId" = $3 + AND $1 <> ALL(options);`, + [option, attributeName, member.tenantId], + ) + } catch (err) { + throw new Error(err) + } + } + } + + // Check if the attribute does not exist and it is not a default attribute + if (!(member.attributes[attributeName] || attribute.default)) { + // Create new attribute if it does not exist + try { + if (attribute.type === MemberAttributeType.MULTI_SELECT) { + await tx.query( + `INSERT INTO "memberAttributeSettings" (id, "tenantId", name, label, type, show, "canDelete", options, "createdAt", "updatedAt") + VALUES ($1, $2, $3, $4, $5, $6, $7, $8, NOW(), NOW()) + ON CONFLICT (name, "tenantId") DO UPDATE + SET options = array_append("memberAttributeSettings".options, $9), "updatedAt" = NOW();`, + [ + generateUUIDv4(), + member.tenantId, + attributeName, + MemberEnrichmentAttributes[attributeName]?.label || + MemberAttributes[attributeName].label, + attribute?.type || + MemberEnrichmentAttributes[attributeName]?.type || + MemberAttributes[attributeName].type || + MemberAttributeType.STRING, + attributeName !== MemberEnrichmentAttributeName.EMAILS, + false, + value, + ], + ) + } else { + await tx.query( + `INSERT INTO "memberAttributeSettings" (id, "tenantId", name, label, type, show, "canDelete", options, "createdAt", "updatedAt") + VALUES ($1, $2, $3, $4, $5, $6, $7, $8, NOW(), NOW()) + ON CONFLICT (name, "tenantId") DO NOTHING;`, + [ + generateUUIDv4(), + member.tenantId, + attributeName, + MemberEnrichmentAttributes[attributeName]?.label || + MemberAttributes[attributeName].label, + attribute?.type || + MemberEnrichmentAttributes[attributeName]?.type || + MemberAttributes[attributeName].type || + MemberAttributeType.STRING, + attributeName !== MemberEnrichmentAttributeName.EMAILS, + false, + null, + ], + ) + } + } catch (err) { + throw new Error(err) + } + } +} diff --git a/services/apps/premium/members_enrichment_worker/src/workflows.ts b/services/apps/premium/members_enrichment_worker/src/workflows.ts new file mode 100644 index 0000000000..4abb86310c --- /dev/null +++ b/services/apps/premium/members_enrichment_worker/src/workflows.ts @@ -0,0 +1,4 @@ +import { getMembersToEnrich } from './workflows/getMembersToEnrich' +import { enrichMember } from './workflows/enrichMember' + +export { getMembersToEnrich, enrichMember } diff --git a/services/apps/premium/members_enrichment_worker/src/workflows/enrichMember.ts b/services/apps/premium/members_enrichment_worker/src/workflows/enrichMember.ts new file mode 100644 index 0000000000..6ae18e5b12 --- /dev/null +++ b/services/apps/premium/members_enrichment_worker/src/workflows/enrichMember.ts @@ -0,0 +1,116 @@ +import { proxyActivities } from '@temporalio/workflow' + +import { IMember } from '@crowd/types' +import { EnrichmentAPIMember } from '@crowd/types/premium' + +import * as activities from '../activities' +import { EnrichingMember } from 'types/enrichment' + +// Configure timeouts and retry policies to enrich members via third-party +// services. +const { enrichMemberUsingGitHubHandle, enrichMemberUsingEmailAddress } = proxyActivities< + typeof activities +>({ startToCloseTimeout: '10 seconds' }) + +// Configure timeouts and retry policies to update member, attributes, merge +// suggestions and related organizations in the database. +const { normalizeEnrichedMember, updateMergeSuggestions, updateOrganizations } = proxyActivities< + typeof activities +>({ startToCloseTimeout: '30 seconds' }) + +// Configure timeouts and retry policies to sync enriched data to OpenSearch. +const { syncMembersToOpensearch, syncOrganizationsToOpensearch } = proxyActivities< + typeof activities +>({ startToCloseTimeout: '120 seconds' }) + +/* +enrichMember is a Temporal workflow that: + - [Activity]: Fetch enriching data from a third-party provider using either the + member's GitHub username or email address. + - [Activity]: Normalize and update member in the database given the enriched + data received. + - [Activity]: Update member's merge suggestions in the database. + - [Activity]: Update member's related organizations in the database. + - [Activity]: Sync newly enriched member from database to OpenSearch. + - [Activity]: Sync newly enriched organization(s) from database to OpenSearch. +*/ +export async function enrichMember(input: IMember): Promise { + let enriched: EnrichmentAPIMember = null + + // Enrich using GitHub if possible. + if (input.username['github']) { + try { + enriched = await enrichMemberUsingGitHubHandle({ + member: input, + }) + } catch (err) { + throw new Error(err) + } + } + + // Otherwise try with email address. + if (!enriched && input.emails.length) { + try { + enriched = await enrichMemberUsingEmailAddress({ + member: input, + }) + } catch (err) { + throw new Error(err) + } + } + + try { + await normalizeEnrichedMember({ + member: input, + enrichment: enriched, + }) + } catch (err) { + throw new Error(err) + } + + // No need to continue if no data has been enriched. + if (!enriched) { + return { + member: input, + enrichment: null, + } + } + + try { + await updateMergeSuggestions({ + member: input, + enrichment: enriched, + }) + } catch (err) { + throw new Error(err) + } + + let organizations: string[] + try { + organizations = await updateOrganizations({ + member: input, + enrichment: enriched, + }) + } catch (err) { + throw new Error(err) + } + + try { + await syncMembersToOpensearch([input.id]) + } catch (err) { + throw new Error(err) + } + + if (organizations.length > 0) { + try { + await syncOrganizationsToOpensearch(organizations) + } catch (err) { + throw new Error(err) + } + } + + return { + member: input, + enrichment: enriched, + } +} diff --git a/services/apps/premium/members_enrichment_worker/src/workflows/getMembersToEnrich.ts b/services/apps/premium/members_enrichment_worker/src/workflows/getMembersToEnrich.ts new file mode 100644 index 0000000000..2a0dc9595b --- /dev/null +++ b/services/apps/premium/members_enrichment_worker/src/workflows/getMembersToEnrich.ts @@ -0,0 +1,48 @@ +import { + proxyActivities, + startChild, + ParentClosePolicy, + ChildWorkflowCancellationType, +} from '@temporalio/workflow' + +import * as activities from '../activities/getMembers' +import { enrichMember } from './enrichMember' + +// Configure timeouts and retry policies to retrieve members to enrich from the +// database. +const { getMembers } = proxyActivities({ + startToCloseTimeout: '75 seconds', +}) + +/* +getMembersToEnrich is a Temporal workflow that: + - [Activity]: Get a set of available members to enrich. + - [Child Workflow]: Enrich, update, and sync everything related to the member + and their organizations in the database and OpenSearch. Child workflows are + completely "detached" from the parent workflow, meaning they will continue + to run and not be cancelled even if this one is. +*/ +export async function getMembersToEnrich(): Promise { + const members = await getMembers() + + await Promise.all( + members.map((member) => { + return startChild(enrichMember, { + workflowId: 'member-enrichment/' + member.tenantId + '/' + member.id, + cancellationType: ChildWorkflowCancellationType.ABANDON, + parentClosePolicy: ParentClosePolicy.PARENT_CLOSE_POLICY_ABANDON, + workflowExecutionTimeout: '15 minutes', + retry: { + backoffCoefficient: 2, + maximumAttempts: 10, + initialInterval: 2 * 1000, + maximumInterval: 30 * 1000, + }, + args: [member], + searchAttributes: { + TenantId: [member.tenantId], + }, + }) + }), + ) +} diff --git a/services/apps/premium/members_enrichment_worker/tsconfig.json b/services/apps/premium/members_enrichment_worker/tsconfig.json new file mode 100644 index 0000000000..bf5ba4932d --- /dev/null +++ b/services/apps/premium/members_enrichment_worker/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "target": "es2017", + "module": "Node16", + "lib": ["es6", "es7", "es2017", "es2017.object", "es2015.promise"], + "skipLibCheck": true, + "sourceMap": true, + "moduleResolution": "node16", + "experimentalDecorators": true, + "esModuleInterop": true, + "baseUrl": "./src", + "paths": { + "@crowd/*/premium": ["../../../../libs/*/src/premium"], + "@crowd/*": ["../../../../libs/*/src"], + "@crowd/archetype-*": ["../../../../archetypes/*/src"] + } + }, + "include": ["src/**/*"] +} diff --git a/services/apps/premium/organizations_enrichment_worker/.eslintrc.cjs b/services/apps/premium/organizations_enrichment_worker/.eslintrc.cjs new file mode 100644 index 0000000000..25ba4e0d66 --- /dev/null +++ b/services/apps/premium/organizations_enrichment_worker/.eslintrc.cjs @@ -0,0 +1,21 @@ +module.exports = { + parser: '@typescript-eslint/parser', + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:prettier/recommended', + ], + plugins: ['@typescript-eslint', 'prettier'], + parserOptions: { + ecmaVersion: 2022, + sourceType: 'module', + }, + env: { + es6: true, + node: true, + }, + rules: { + 'prettier/prettier': 'error', + '@typescript-eslint/explicit-module-boundary-types': 'off', + }, +} diff --git a/services/apps/premium/organizations_enrichment_worker/.prettierignore b/services/apps/premium/organizations_enrichment_worker/.prettierignore new file mode 100644 index 0000000000..2b24877309 --- /dev/null +++ b/services/apps/premium/organizations_enrichment_worker/.prettierignore @@ -0,0 +1,3 @@ +dist/ +.eslintrc.cjs +.prettierrc.cjs diff --git a/services/apps/premium/organizations_enrichment_worker/.prettierrc.cjs b/services/apps/premium/organizations_enrichment_worker/.prettierrc.cjs new file mode 100644 index 0000000000..a8ca459839 --- /dev/null +++ b/services/apps/premium/organizations_enrichment_worker/.prettierrc.cjs @@ -0,0 +1,7 @@ +module.exports = { + singleQuote: true, + arrowParens: 'always', + printWidth: 100, + trailingComma: 'all', + semi: false, +} diff --git a/services/apps/premium/organizations_enrichment_worker/package.json b/services/apps/premium/organizations_enrichment_worker/package.json new file mode 100644 index 0000000000..08b7678ea7 --- /dev/null +++ b/services/apps/premium/organizations_enrichment_worker/package.json @@ -0,0 +1,44 @@ +{ + "name": "@crowd/organizations-enrichment-worker", + "version": "1.0.0", + "private": true, + "scripts": { + "start": "CROWD_TEMPORAL_TASKQUEUE=organizations-enrichment SERVICE=organizations-enrichment-worker TS_NODE_TRANSPILE_ONLY=true node -r tsconfig-paths/register -r ts-node/register src/main.ts", + "start:debug:local": "set -a && . ../../../../backend/.env.dist.local && . ../../../../backend/.env.override.local && set +a && CROWD_TEMPORAL_TASKQUEUE=organizations-enrichment SERVICE=organizations-enrichment-worker TS_NODE_TRANSPILE_ONLY=true LOG_LEVEL=trace node --inspect=0.0.0.0:9232 -r tsconfig-paths/register -r ts-node/register src/main.ts", + "start:debug": "CROWD_TEMPORAL_TASKQUEUE=organizations-enrichment SERVICE=organizations-enrichment-worker TS_NODE_TRANSPILE_ONLY=true LOG_LEVEL=trace node --inspect=0.0.0.0:9232 -r tsconfig-paths/register -r ts-node/register src/main.ts", + "dev:local": "./node_modules/.bin/nodemon --watch src --watch ../../../libs --ext ts --exec pnpm run start:debug:local", + "dev": "./node_modules/.bin/nodemon --watch src --watch ../../../libs --ext ts --exec pnpm run start:debug", + "lint": "./node_modules/.bin/eslint --ext .ts src --max-warnings=0", + "format": "./node_modules/.bin/prettier --write \"src/**/*.ts\"", + "format-check": "./node_modules/.bin/prettier --check .", + "tsc-check": "./node_modules/.bin/tsc --noEmit" + }, + "dependencies": { + "@crowd/archetype-standard": "file:../../../archetypes/standard", + "@crowd/archetype-worker": "file:../../../archetypes/worker", + "@crowd/common": "file:../../../libs/common", + "@crowd/database": "file:../../../libs/database", + "@crowd/logging": "file:../../../libs/logging", + "@crowd/redis": "file:../../../libs/redis", + "@crowd/feature-flags": "file:../../../libs/feature-flags", + "@crowd/common_services": "file:../../../libs/common_services", + "@crowd/types": "file:../../../libs/types", + "@temporalio/client": "~1.8.6", + "@temporalio/workflow": "~1.8.6", + "peopledatalabs": "~6.1.5", + "ts-node": "^10.9.1", + "tsconfig-paths": "^4.2.0", + "typescript": "^5.2.2" + }, + "devDependencies": { + "@types/node": "^20.8.2", + "@types/uuid": "~9.0.6", + "@typescript-eslint/eslint-plugin": "^6.7.4", + "@typescript-eslint/parser": "^6.7.4", + "eslint": "^8.50.0", + "eslint-config-prettier": "^9.0.0", + "eslint-plugin-prettier": "^5.0.0", + "nodemon": "^3.0.1", + "prettier": "^3.0.3" + } +} diff --git a/services/apps/premium/organizations_enrichment_worker/src/activities.ts b/services/apps/premium/organizations_enrichment_worker/src/activities.ts new file mode 100644 index 0000000000..b46dcc2269 --- /dev/null +++ b/services/apps/premium/organizations_enrichment_worker/src/activities.ts @@ -0,0 +1,19 @@ +import { + getRemainingTenantCredits, + incrementTenantCredits, + getTenantOrganizationsForEnrichment, + tryEnrichOrganization, + getApplicableTenants, + hasTenantOrganizationEnrichmentEnabled, + syncToOpensearch, +} from './activities/organizationEnrichment' + +export { + getApplicableTenants, + getRemainingTenantCredits, + incrementTenantCredits, + getTenantOrganizationsForEnrichment, + tryEnrichOrganization, + hasTenantOrganizationEnrichmentEnabled, + syncToOpensearch, +} diff --git a/services/apps/premium/organizations_enrichment_worker/src/activities/organizationEnrichment.ts b/services/apps/premium/organizations_enrichment_worker/src/activities/organizationEnrichment.ts new file mode 100644 index 0000000000..1cffece003 --- /dev/null +++ b/services/apps/premium/organizations_enrichment_worker/src/activities/organizationEnrichment.ts @@ -0,0 +1,528 @@ +import { + EDITION, + IS_DEV_ENV, + IS_TEST_ENV, + distinct, + distinctBy, + getSecondsTillEndOfMonth, + renameKeys, +} from '@crowd/common' +import { Logger, getChildLogger } from '@crowd/logging' +import { RedisCache } from '@crowd/redis' +import { + Edition, + FeatureFlag, + FeatureFlagRedisKey, + IEnrichableOrganization, + PLAN_LIMITS, + PlatformType, + TenantPlans, +} from '@crowd/types' +import { svc } from '../main' +import { + IOrganizationData, + IOrganizationIdentity, + OrganizationRepository, +} from '../repos/organization.repo' +import { IPremiumTenantInfo, TenantRepository } from '../repos/tenant.repo' +import { isFeatureEnabled } from '@crowd/feature-flags' +import { ENRICHMENT_PLATFORM_PRIORITY } from '../types/common' +import { + PriorityLevelContextRepository, + QueuePriorityContextLoader, + SearchSyncWorkerEmitter, +} from '@crowd/common_services' + +/* eslint-disable @typescript-eslint/no-explicit-any */ + +const MAX_ENRICHED_ORGANIZATIONS_PER_EXECUTION = + IS_DEV_ENV || IS_TEST_ENV ? 10 : EDITION === Edition.LFX ? 500 : 100 + +let searchSyncWorkerEmitter: SearchSyncWorkerEmitter | undefined +async function getSearchSyncWorkerEmitter(): Promise { + if (searchSyncWorkerEmitter) { + if (!searchSyncWorkerEmitter.isInitialized()) { + await searchSyncWorkerEmitter.init() + } + + return searchSyncWorkerEmitter + } + + const repo = new PriorityLevelContextRepository(svc.postgres.reader, svc.log) + const loader: QueuePriorityContextLoader = (tenantId: string) => + repo.loadPriorityLevelContext(tenantId) + + searchSyncWorkerEmitter = new SearchSyncWorkerEmitter( + svc.sqs, + svc.redis, + svc.tracer, + svc.unleash, + loader, + svc.log, + ) + + await searchSyncWorkerEmitter.init() + + return searchSyncWorkerEmitter +} + +export async function syncToOpensearch(tenantId: string, organizationId: string): Promise { + const log = getChildLogger(syncToOpensearch.name, svc.log, { + organizationId, + }) + + try { + const searchSyncWorkerEmitter = await getSearchSyncWorkerEmitter() + await searchSyncWorkerEmitter.triggerOrganizationSync(tenantId, organizationId, false) + } catch (err) { + log.error(err, 'Error while syncing organization to OpenSearch!') + throw new Error(err) + } + + return null +} + +export async function getApplicableTenants( + page: number, + lastId?: string, +): Promise { + const log = getChildLogger(getApplicableTenants.name, svc.log) + + log.debug('Getting applicable tenants!') + const repo = new TenantRepository(svc.postgres.reader, svc.log) + const tenants = await repo.getPremiumTenants(page, lastId) + + log.debug(`Got ${tenants.length} applicable tenants!`) + + return tenants +} + +export async function hasTenantOrganizationEnrichmentEnabled(tenantId: string): Promise { + const log = getChildLogger(hasTenantOrganizationEnrichmentEnabled.name, svc.log, { + tenantId, + }) + + const result = await isFeatureEnabled( + FeatureFlag.TEMPORAL_ORGANIZATION_ENRICHMENT, + async () => { + return { + tenantId, + } + }, + svc.unleash, + svc.redis, + 5 * 60, + tenantId, + ) + + log.debug({ tenantId, enabled: result }, 'Tenant organization enrichment enabled?') + return result +} + +/** + * Calculate how many credits the tenant has left for organization enrichment + * @param tenant + * @returns number of credits left for the tenant that can be used to enrich organizations + */ +export async function getRemainingTenantCredits(tenant: IPremiumTenantInfo): Promise { + const log = getChildLogger(getRemainingTenantCredits.name, svc.log, { tenantId: tenant.id }) + if (tenant.plan === TenantPlans.Growth) { + // need to check how many credits the tenant has left + const cache = new RedisCache(FeatureFlagRedisKey.ORGANIZATION_ENRICHMENT_COUNT, svc.redis, log) + const cached = await cache.get(tenant.id) + if (!cached) { + await cache.set(tenant.id, '0', getSecondsTillEndOfMonth()) + } + const usedCredits = parseInt(cached ?? '0', 10) + const remainingCredits = + PLAN_LIMITS[TenantPlans.Growth][FeatureFlag.ORGANIZATION_ENRICHMENT] - usedCredits + + const toSpend = Math.min(remainingCredits, MAX_ENRICHED_ORGANIZATIONS_PER_EXECUTION) + + log.info( + { tenantId: tenant.id }, + `Tenant has ${remainingCredits} credits left. Spending ${toSpend} credits.`, + ) + return toSpend + } + + if ([TenantPlans.Enterprise, TenantPlans.Scale].includes(tenant.plan)) { + log.info( + { tenantId: tenant.id }, + `Tenant has unlimited credits. Spending ${MAX_ENRICHED_ORGANIZATIONS_PER_EXECUTION} credits.`, + ) + return MAX_ENRICHED_ORGANIZATIONS_PER_EXECUTION + } + + throw new Error(`Only premium tenant plans are supported - got ${tenant.plan}!`) +} + +/** + * Increment tenant organization enrichment credits by 1 + * @param tenantId + */ +export async function incrementTenantCredits(tenantId: string, plan: TenantPlans): Promise { + const log = getChildLogger(incrementTenantCredits.name, svc.log, { tenantId }) + + if (plan === TenantPlans.Growth) { + log.debug({ tenantId }, `Incrementing tenant credits.`) + const cache = new RedisCache(FeatureFlagRedisKey.ORGANIZATION_ENRICHMENT_COUNT, svc.redis, log) + + await cache.increment(tenantId, 1, getSecondsTillEndOfMonth()) + } +} + +/** + * Fetch organizations ids that need to be enriched + * This is those who have lastEnrichedAt set to null or they haven't been enriched in the last 3 months + * @param tenantId + * @param perPage + * @param lastId + * @returns + */ +export async function getTenantOrganizationsForEnrichment( + tenantId: string, + perPage: number, + page: number, +): Promise { + const log = getChildLogger(getTenantOrganizationsForEnrichment.name, svc.log, { tenantId }) + const repo = new OrganizationRepository(svc.postgres.reader, svc.log) + const organizationIds = await repo.getTenantOrganizationsToEnrich(tenantId, perPage, page) + log.info({ tenantId, nrOrgs: organizationIds.length }, 'Got organizations for enrichment!') + return organizationIds +} + +/** + * Attempts organization enrichment. + * @param tenantId + * @param organizationId + * @returns true if organization was enriched, false otherwise + */ +export async function tryEnrichOrganization( + tenantId: string, + organizationId: string, +): Promise { + const log = getChildLogger(tryEnrichOrganization.name, svc.log, { + tenantId, + organizationId, + }) + + log.debug('Trying to enrich an organization!') + + const repo = new OrganizationRepository(svc.postgres.writer, log) + + const orgData = await repo.getOrganizationData(organizationId) + + if (!orgData) { + log.warn('Organization not found!') + return false + } + + const identityPlatforms = distinct(orgData.identities.map((i) => i.platform)) + + if (identityPlatforms.length > 0) { + const platformsForEnrichment = ENRICHMENT_PLATFORM_PRIORITY.filter((p) => + identityPlatforms.includes(p), + ) + + if (platformsForEnrichment.length > 0 || orgData.website) { + const platformToUseForEnrichment = platformsForEnrichment[0] + const identityForEnrichment = orgData.identities.find( + (i) => i.platform === platformToUseForEnrichment, + ) + + // we use website and identityForEnrichment?.name to enrich the organization + const enrichmentData = await getEnrichment( + { + website: orgData.website, + name: identityForEnrichment?.name, + }, + log, + ) + + if (enrichmentData) { + log.debug('Enrichment data found!') + const finalData = convertEnrichedDataToOrg(enrichmentData, orgData.identities) + finalData.weakIdentities = orgData.weakIdentities + await prepareIdentities(orgData.tenantId, orgData.id, finalData, repo) + + let website: string | undefined + let checkIfWebsiteIsTaken = false + if (orgData.website && finalData.website && orgData.website !== finalData.website) { + log.debug('Website changed!') + website = finalData.website + checkIfWebsiteIsTaken = true + } else if (orgData.website) { + website = orgData.website + } else if (finalData.website) { + log.debug('Website found!') + website = finalData.website + checkIfWebsiteIsTaken = true + } + + if ( + checkIfWebsiteIsTaken && + repo.anyOtherOrganizationWithTheSameWebsite(orgData.id, orgData.tenantId, orgData.website) + ) { + log.debug('Website is already taken!') + // we can't set this website in the database due to unique constraint but we can generate merge suggestions based on it + finalData.website = undefined + } + + await repo.transactionally(async (t) => { + await t.updateIdentities( + orgData.id, + orgData.tenantId, + orgData.identities, + finalData.identities, + ) + await t.updateOrganizationWithEnrichedData(orgData, finalData) + + if (website) { + log.debug({ website }, 'Generating merge suggestions!') + await t.generateMergeSuggestions(orgData.id, orgData.tenantId, website) + } + }) + + log.debug('Enrichment done!') + } else { + log.debug('No enrichment data found!') + await repo.markEnriched(organizationId) + } + + return true + } else { + log.warn('Organization does not have a website and no identities with enrichment platforms!') + } + } else { + log.warn('Organization has no activities or identities and therefore it will not be enriched!') + } + + return false +} + +async function prepareIdentities( + tenantId: string, + organizationId: string, + orgData: IOrganizationData, + repo: OrganizationRepository, +): Promise { + // find identities belonging to other orgs that match the ones in the orgData identities and weakIdentities + const allIdentities = orgData.identities.concat(orgData.weakIdentities) + let existingIdentities = await repo.findIdentities(tenantId, organizationId, allIdentities) + existingIdentities = distinctBy(existingIdentities, (i) => `${i.platform}:${i.name}`) + + const weakIdentities: IOrganizationIdentity[] = [] + const identities: IOrganizationIdentity[] = [] + + for (const identity of allIdentities) { + // check if any other org has this identity + if ( + existingIdentities.find((i) => i.platform === identity.platform && i.name === identity.name) + ) { + // this identity should be a weak one because some other org has this identity as well + weakIdentities.push(identity) + } else { + // this identity should be a strong one because no other org has this identity + identities.push(identity) + } + } + + // set it + orgData.identities = identities + orgData.weakIdentities = weakIdentities +} + +/** + * Fetch enrichment data from PDL Company API + * @param enrichmentInput - The object that contains organization enrichment attributes + * @returns the PDL company response + */ +async function getEnrichment({ name, website, locality }: any, log: Logger): Promise { + const PDLJSModule = await import('peopledatalabs') + const PDLClient = new PDLJSModule.default({ + apiKey: process.env['CROWD_ORGANIZATION_ENRICHMENT_API_KEY'], + }) + let data: null | any + try { + const payload: any = {} + + if (name) { + payload.name = name + } + + if (website) { + payload.website = website + } + + data = await PDLClient.company.enrichment(payload) + + if (data.website === 'undefined.es') { + return null + } + + data.name = name + } catch (error) { + if (error.status === 404) { + log.debug({ name, website, locality }, 'PDL data not available!') + } else { + log.error(error, { name, website, locality }, 'Error while fetching PDL data!') + } + + return null + } + return data +} + +function convertEnrichedDataToOrg(pdlData: any, existingIdentities: IOrganizationIdentity[]): any { + let data = renameKeys(pdlData, { + summary: 'description', + employee_count_by_country: 'employeeCountByCountry', + employee_count: 'employees', + location: 'address', + tags: 'tags', + ultimate_parent: 'ultimateParent', + immediate_parent: 'immediateParent', + affiliated_profiles: 'affiliatedProfiles', + all_subsidiaries: 'allSubsidiaries', + alternative_domains: 'alternativeDomains', + alternative_names: 'alternativeNames', + average_employee_tenure: 'averageEmployeeTenure', + average_tenure_by_level: 'averageTenureByLevel', + average_tenure_by_role: 'averageTenureByRole', + direct_subsidiaries: 'directSubsidiaries', + employee_churn_rate: 'employeeChurnRate', + employee_count_by_month: 'employeeCountByMonth', + employee_growth_rate: 'employeeGrowthRate', + employee_count_by_month_by_level: 'employeeCountByMonthByLevel', + employee_count_by_month_by_role: 'employeeCountByMonthByRole', + gics_sector: 'gicsSector', + gross_additions_by_month: 'grossAdditionsByMonth', + gross_departures_by_month: 'grossDeparturesByMonth', + inferred_revenue: 'inferredRevenue', + }) + data = sanitize(data) + + data = enrichSocialNetworks(data, { + profiles: pdlData.profiles, + linkedin_id: pdlData.linkedin_id, + }) + + data.identities = existingIdentities + + if (data.github && data.github.handle) { + const identityExists = data.identities.find( + (i) => i.platform === PlatformType.GITHUB && i.name === data.github.handle, + ) + if (!identityExists) { + data.identities.push({ + name: data.github.handle, + platform: PlatformType.GITHUB, + url: data.github.url || `https://github.com/${data.github.handle}`, + }) + } + } + + if (data.twitter && data.twitter.handle) { + const identityExists = data.identities.find( + (i) => i.platform === PlatformType.TWITTER && i.name === data.twitter.handle, + ) + if (!identityExists) { + data.identities.push({ + name: data.twitter.handle, + platform: PlatformType.TWITTER, + url: data.twitter.url || `https://twitter.com/${data.twitter.handle}`, + }) + } + } + + if (data.linkedin && data.linkedin.handle) { + const identityExists = data.identities.find( + (i) => i.platform === PlatformType.LINKEDIN && i.name === data.linkedin.handle, + ) + if (!identityExists) { + data.identities.push({ + name: data.linkedin.handle, + platform: PlatformType.LINKEDIN, + url: data.linkedin.url || `https://linkedin.com/company/${data.linkedin.handle}`, + }) + } + } + + // Set displayName using the first identity or fallback to website + if (!data.displayName) { + const identity = data.identities[0] + data.displayName = identity ? identity.name : data.website + } + + return data +} + +function sanitize(data: any): any { + if (data.address) { + data.geoLocation = data.address.geo ?? null + delete data.address.geo + data.location = `${data.address.street_address ?? ''} ${data.address.address_line_2 ?? ''} ${ + data.address.name ?? '' + }` + } + if (data.employeeCountByCountry && !data.employees) { + const employees = Object.values(data.employeeCountByCountry).reduce( + (acc, size) => (acc as any) + size, + 0, + ) + Object.assign(data, { employees: employees || data.employees }) + } + if (data.description) { + let description = data.description[0].toUpperCase() + for (let char of data.description.slice(1)) { + if (description.length > 1 && description.slice(-2) === '. ') { + char = char.toUpperCase() + } + description += char + } + data.description = description + } + if (data.inferredRevenue) { + const revenueList = data.inferredRevenue + .replaceAll('$', '') + .split('-') + .map((x) => { + // billions --> millions conversion, if needed + const multiple = x.endsWith('B') ? 1000 : 1 + const value = parseInt(x, 10) * multiple + return value + }) + + data.revenueRange = { + min: revenueList[0], + max: revenueList[1], + } + } + + return data +} + +function enrichSocialNetworks( + data: IEnrichableOrganization, + socialNetworks: { + profiles: any + linkedin_id: any + }, +): IEnrichableOrganization { + const socials = socialNetworks.profiles.reduce((acc, social) => { + const platform = social.split('.')[0] + const handle = social.split('/').splice(-1)[0] + if ( + Object.values(PlatformType).includes(platform as any) && + handle !== socialNetworks.linkedin_id + ) { + acc[platform] = { + handle, + [platform === PlatformType.TWITTER ? 'site' : 'url']: social, + } + } + return acc + }, {}) + return { ...data, ...socials } +} diff --git a/services/apps/premium/organizations_enrichment_worker/src/main.ts b/services/apps/premium/organizations_enrichment_worker/src/main.ts new file mode 100644 index 0000000000..d12fefec71 --- /dev/null +++ b/services/apps/premium/organizations_enrichment_worker/src/main.ts @@ -0,0 +1,35 @@ +import { Config } from '@crowd/archetype-standard' +import { ServiceWorker, Options } from '@crowd/archetype-worker' +import { scheduleOrganizationsEnrichment } from './schedules' + +const config: Config = { + envvars: ['CROWD_ORGANIZATION_ENRICHMENT_API_KEY'], + producer: { + enabled: false, + }, + temporal: { + enabled: true, + }, + redis: { + enabled: true, + }, +} + +const options: Options = { + postgres: { + enabled: true, + }, + sqs: { + enabled: true, + }, +} + +export const svc = new ServiceWorker(config, options) + +setImmediate(async () => { + await svc.init() + + await scheduleOrganizationsEnrichment() + + await svc.start() +}) diff --git a/services/apps/premium/organizations_enrichment_worker/src/repos/organization.repo.ts b/services/apps/premium/organizations_enrichment_worker/src/repos/organization.repo.ts new file mode 100644 index 0000000000..7ca66ee1a5 --- /dev/null +++ b/services/apps/premium/organizations_enrichment_worker/src/repos/organization.repo.ts @@ -0,0 +1,510 @@ +import { EDITION, singleOrDefault } from '@crowd/common' +import { DbStore, RepositoryBase } from '@crowd/database' +import { Logger } from '@crowd/logging' +import { Edition } from '@crowd/types' +import { ENRICHMENT_PLATFORM_PRIORITY } from '../types/common' + +/* eslint-disable @typescript-eslint/no-explicit-any */ + +export class OrganizationRepository extends RepositoryBase { + constructor(dbStore: DbStore, parentLog: Logger) { + super(dbStore, parentLog) + } + + public async getTenantOrganizationsToEnrich( + tenantId: string, + perPage: number, + page: number, + ): Promise { + const parameters: Record = { + tenantId, + } + + const conditions = [ + 'o."tenantId" = $(tenantId)', + 'o."deletedAt" is null', + `(o."lastEnrichedAt" is null or o."lastEnrichedAt" < now() - interval '3 months')`, + ] + + if (EDITION === Edition.LFX) { + conditions.push('ad."activityCount" >= 3') + } else { + conditions.push(`ad."lastActive" > now() - interval '1 year'`) + + // this is guaranteed for now by the inner join just leaving it here for future reference + // conditions.push(`ad."activityCount" >= 1`) + } + + const query = ` + with activity_data as (select "organizationId", + count(id) as "activityCount", + max(timestamp) as "lastActive" + from activities + where "tenantId" = $(tenantId) + and "deletedAt" is null + group by "organizationId"), + identities as (select oi."organizationId", + json_agg(json_build_object( + 'platform', oi.platform, + 'name', oi.name, + 'url', oi.url + )) as "identities" + from "organizationIdentities" oi + where oi."tenantId" = $(tenantId) and oi.platform in (${ENRICHMENT_PLATFORM_PRIORITY.map( + (p) => `'${p}'`, + ).join(', ')}) + group by oi."organizationId") + select o.id + from organizations o + inner join activity_data ad on ad."organizationId" = o.id + inner join identities i on i."organizationId" = o.id + where ${conditions.join(' and ')} + order by ad."activityCount" desc + limit ${perPage} offset ${(page - 1) * perPage}; + ` + + const results = await this.db().any(query, parameters) + + return results.map((r) => r.id) + } + + public async getOrganizationData(organizationId: string): Promise { + return await this.db().oneOrNone( + ` + with identities as (select oi."organizationId", + json_agg(json_build_object( + 'platform', oi.platform, + 'name', oi.name, + 'url', oi.url + )) as "identities" + from "organizationIdentities" oi + where oi."organizationId" = $(organizationId) + group by oi."organizationId") + select o.id, + o.description, + o.emails, + o."phoneNumbers", + o.logo, + o.tags, + o.twitter, + o.linkedin, + o.crunchbase, + o.employees, + o."revenueRange", + o."tenantId", + o.location, + o.github, + o.website, + o."employeeCountByCountry", + o.type, + o."geoLocation", + o.size, + o.ticker, + o.headline, + o.profiles, + o.naics, + o.address, + o.industry, + o.founded, + o."displayName", + o."affiliatedProfiles", + o."allSubsidiaries", + o."alternativeDomains", + o."alternativeNames", + o."averageEmployeeTenure", + o."averageTenureByLevel", + o."averageTenureByRole", + o."directSubsidiaries", + o."employeeChurnRate", + o."employeeCountByMonth", + o."employeeGrowthRate", + o."employeeCountByMonthByLevel", + o."employeeCountByMonthByRole", + o."gicsSector", + o."grossAdditionsByMonth", + o."grossDeparturesByMonth", + o."ultimateParent", + o."immediateParent", + o."weakIdentities", + o."manuallyChangedFields", + i.identities + from organizations o + inner join identities i on o.id = i."organizationId" + where o.id = $(organizationId); + `, + { + organizationId, + }, + ) + } + + public async markEnriched(organizationId: string): Promise { + await this.db().none( + ` + update organizations + set "lastEnrichedAt" = now() + where id = $(organizationId) + `, + { + organizationId, + }, + ) + } + + public async updateIdentities( + organizationId: string, + tenantId: string, + existingIdentities: IOrganizationIdentity[], + newIdentities: IOrganizationIdentity[], + ): Promise { + // check which identities are new or updated + // according to the unique key one tenant can have only one identity per platform + const toCreate: IOrganizationIdentity[] = [] + const toUpdate: IOrganizationIdentity[] = [] + + for (const newIdentity of newIdentities) { + const existingIdentity = singleOrDefault( + existingIdentities, + (i) => i.platform === newIdentity.platform && i.name === newIdentity.name, + ) + + if (existingIdentity) { + // we are only updating the url if needed nothing else + if (existingIdentity.url !== newIdentity.url) { + toUpdate.push(newIdentity) + } + } else { + toCreate.push(newIdentity) + } + } + + const queries: string[] = [] + + if (toUpdate.length > 0) { + // generate bulk update query + const entries = toUpdate.map((i) => { + return { + name: i.name, + platform: i.platform, + organizationId, + tenantId, + url: i.url, + } + }) + + const query = + this.dbInstance.helpers.update( + entries, + ['?organizationId', '?tenantId', '?platform', '?name', 'url'], + 'organizationIdentities', + ) + + ' where t."organizationId" = v."organizationId"::uuid and t.platform = v.platform and t.name = v.name and t."tenantId" = v."tenantId"::uuid' + + queries.push(query) + } + + if (toCreate.length > 0) { + // generate bulk insert query + const entries = toCreate.map((i) => { + return { + name: i.name, + platform: i.platform, + organizationId, + tenantId, + url: i.url, + } + }) + + const query = + this.dbInstance.helpers.insert( + entries, + ['organizationId', 'tenantId', 'platform', 'name', 'url'], + 'organizationIdentities', + ) + ` on conflict do nothing` + + queries.push(query) + } + + if (queries.length > 0) { + await Promise.all(queries.map((q) => this.db().none(q))) + } + } + + public async findIdentities( + tenantId: string, + organizationId: string, + identities: IOrganizationIdentity[], + ): Promise { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const params: any = { + tenantId, + organizationId, + } + + const identityParams = identities + .map( + (identity) => + `(${this.dbInstance.as.text(identity.platform)}, ${this.dbInstance.as.text( + identity.name, + )})`, + ) + .join(', ') + + const results = await this.db().any( + ` + with input_identities (platform, name) as ( + values ${identityParams} + ) + select oi.url, i.platform, i.name + from "organizationIdentities" oi + inner join input_identities i on oi.platform = i.platform and oi.name = i.name + where oi."tenantId" = $(tenantId) and oi."organizationId" <> $(organizationId) +`, + params, + ) + + return results + } + + private static readonly ENRICHABLE_ORGANIZATION_FIELDS = [ + 'description', + 'emails', + 'phoneNumbers', + 'logo', + 'tags', + 'twitter', + 'linkedin', + 'crunchbase', + 'employees', + 'revenueRange', + 'location', + 'github', + 'website', + 'employeeCountByCountry', + 'type', + 'geoLocation', + 'size', + 'ticker', + 'headline', + 'profiles', + 'naics', + 'address', + 'industry', + 'founded', + 'affiliatedProfiles', + 'allSubsidiaries', + 'alternativeDomains', + 'alternativeNames', + 'averageEmployeeTenure', + 'averageTenureByLevel', + 'averageTenureByRole', + 'directSubsidiaries', + 'employeeChurnRate', + 'employeeCountByMonth', + 'employeeGrowthRate', + 'employeeCountByMonthByLevel', + 'employeeCountByMonthByRole', + 'gicsSector', + 'grossAdditionsByMonth', + 'grossDeparturesByMonth', + 'ultimateParent', + 'immediateParent', + ] + + public async updateOrganizationWithEnrichedData( + originalData: IOrganizationData, + enrichedData: any, + ): Promise { + const manuallyChangedFields = originalData.manuallyChangedFields || [] + + const toUpdate: Record = {} + + if ( + originalData.displayName === null || + (originalData.displayName.trim() === '' && enrichedData.displayName) + ) { + toUpdate.displayName = enrichedData.displayName + } + + for (const field of OrganizationRepository.ENRICHABLE_ORGANIZATION_FIELDS) { + if (manuallyChangedFields.includes(field)) { + continue + } + + if (field in enrichedData) { + const enrichedValue = enrichedData[field] + + // ignore null/undefined/empty string values + if ( + enrichedValue === null || + enrichedValue === undefined || + (typeof enrichedValue === 'string' && enrichedValue.trim() === '') + ) { + continue + } + + const existingValue = originalData[field] + + if (typeof enrichedValue === 'object') { + // compare stringified objects + if (JSON.stringify(enrichedValue) === JSON.stringify(existingValue)) { + continue + } + } else if (enrichedValue === existingValue) { + continue + } + + toUpdate[field] = enrichedValue + } + } + + const keysToUpdate = Object.keys(toUpdate) + if (keysToUpdate.length > 0) { + this.log.debug( + { organizationId: originalData.id }, + `Updating organization with enriched data! With ${keysToUpdate.length} fields`, + ) + + if (toUpdate.naics) { + toUpdate.naics = JSON.stringify(toUpdate.naics) + } + + // set lastEnrichedAt to now + keysToUpdate.push('lastEnrichedAt') + toUpdate.lastEnrichedAt = new Date() + + const query = this.dbInstance.helpers.update(toUpdate, keysToUpdate, 'organizations') + + const result = await this.db().result(`${query} where id = $(id)`, { + ...toUpdate, + id: originalData.id, + }) + + this.checkUpdateRowCount(result.rowCount, 1) + } else { + await this.markEnriched(originalData.id) + } + } + + public async anyOtherOrganizationWithTheSameWebsite( + organizationId: string, + tenantId: string, + website: string, + ): Promise { + const res = await this.db().oneOrNone( + `select 1 from organizations where + "tenantId" = $(tenantId) + and id <> $(organizationId) + and website = $(website)`, + { + tenantId, + organizationId, + website, + }, + ) + + if (res) { + return true + } + + return false + } + + public async generateMergeSuggestions( + organizationId: string, + tenantId: string, + website: string, + ): Promise { + await this.db().none( + ` + insert into "organizationToMerge"("organizationId", "toMergeId", "similarity", "createdAt", "updatedAt") + -- find all organization caches that have this website + with applicable_organization_caches as (select distinct id + from "organizationCacheIdentities" + where website = $(website)), + -- then find all organizations that are connected to that cache + -- and are in the correct tenant and are not the same as the organization we are enriching + applicable_organizations as (select o.id + from "organizationCacheLinks" ocl + inner join applicable_organization_caches aoc on ocl."organizationCacheId" = aoc.id + inner join organizations o on ocl."organizationId" = o.id + where o."tenantId" = $(tenantId) + and o.id <> $(organizationId)) + -- then again filter out the ones that are already in the toMerge and noMerge tables + -- and insert the rest into the toMerge table + select $(organizationId), ao.id, 0.9, now(), now() + from applicable_organizations ao + left join "organizationNoMerge" anm + on anm."organizationId" = $(organizationId) and anm."noMergeId" = ao.id + left join "organizationToMerge" atm + on atm."organizationId" = $(organizationId) and atm."toMergeId" = ao.id + where anm."noMergeId" is null + and atm."toMergeId" is null + -- just in case add this + on conflict do nothing; + `, + { + organizationId, + tenantId, + website, + }, + ) + } +} + +export interface IOrganizationIdentity { + platform: string + name: string + url: string | null +} + +export interface IOrganizationData { + id: string + tenantId: string + description: string | null + emails: string[] | null + phoneNumbers: string[] | null + logo: string | null + tags: string[] | null + twitter: unknown | null + linkedin: unknown | null + crunchbase: unknown | null + employees: number | null + revenueRange: unknown | null + location: string | null + github: unknown | null + website: string | null + employeeCountByCountry: unknown | null + type: string | null + geoLocation: string | null + size: string | null + ticker: string | null + headline: string | null + profiles: string[] | null + naics: unknown[] | null + address: unknown | null + industry: string | null + founded: number | null + displayName: string | null + affiliatedProfiles: string[] | null + allSubsidiaries: string[] | null + alternativeDomains: string[] | null + alternativeNames: string[] | null + averageEmployeeTenure: number | null + averageTenureByLevel: unknown | null + averageTenureByRole: unknown | null + directSubsidiaries: string[] | null + employeeChurnRate: unknown | null + employeeCountByMonth: unknown | null + employeeGrowthRate: unknown | null + employeeCountByMonthByLevel: unknown | null + employeeCountByMonthByRole: unknown | null + gicsSector: string | null + grossAdditionsByMonth: unknown | null + grossDeparturesByMonth: unknown | null + ultimateParent: string | null + immediateParent: string | null + manuallyChangedFields: string[] + identities: IOrganizationIdentity[] + weakIdentities: IOrganizationIdentity[] +} diff --git a/services/apps/premium/organizations_enrichment_worker/src/repos/tenant.repo.ts b/services/apps/premium/organizations_enrichment_worker/src/repos/tenant.repo.ts new file mode 100644 index 0000000000..d88cb4ad28 --- /dev/null +++ b/services/apps/premium/organizations_enrichment_worker/src/repos/tenant.repo.ts @@ -0,0 +1,31 @@ +import { TenantPlans } from '@crowd/types' +import { Logger } from '@crowd/logging' +import { DbStore, RepositoryBase } from '@crowd/database' + +export interface IPremiumTenantInfo { + id: string + plan: TenantPlans +} + +export class TenantRepository extends RepositoryBase { + constructor(dbStore: DbStore, parentLog: Logger) { + super(dbStore, parentLog) + } + + async getPremiumTenants(perPage: number, lastId?: string): Promise { + return await this.db().any( + ` + select id, + plan + from tenants + where plan in ($(plans:csv)) ${lastId ? 'and id > $(lastId)' : ''} + order by id + limit ${perPage}; + `, + { + plans: [TenantPlans.Enterprise, TenantPlans.Growth, TenantPlans.Scale], + lastId, + }, + ) + } +} diff --git a/services/apps/premium/organizations_enrichment_worker/src/schedules.ts b/services/apps/premium/organizations_enrichment_worker/src/schedules.ts new file mode 100644 index 0000000000..3d7430f82f --- /dev/null +++ b/services/apps/premium/organizations_enrichment_worker/src/schedules.ts @@ -0,0 +1,3 @@ +import { scheduleOrganizationsEnrichment } from './schedules/organizationEnrichment' + +export { scheduleOrganizationsEnrichment } diff --git a/services/apps/premium/organizations_enrichment_worker/src/schedules/organizationEnrichment.ts b/services/apps/premium/organizations_enrichment_worker/src/schedules/organizationEnrichment.ts new file mode 100644 index 0000000000..0f0cd5bdaa --- /dev/null +++ b/services/apps/premium/organizations_enrichment_worker/src/schedules/organizationEnrichment.ts @@ -0,0 +1,33 @@ +import { ScheduleAlreadyRunning, ScheduleOverlapPolicy } from '@temporalio/client' +import { svc } from '../main' +import { triggerTenantOrganizationEnrichment } from '../workflows' +import { IS_DEV_ENV, IS_TEST_ENV } from '@crowd/common' + +export const scheduleOrganizationsEnrichment = async () => { + try { + await svc.temporal.schedule.create({ + scheduleId: 'organizations-enrichment', + spec: { + // every hour (at minute 0) + cronExpressions: IS_DEV_ENV || IS_TEST_ENV ? ['*/2 * * * *'] : ['0 * * * *'], + }, + policies: { + overlap: ScheduleOverlapPolicy.BUFFER_ONE, + catchupWindow: '1 minute', + }, + action: { + type: 'startWorkflow', + workflowType: triggerTenantOrganizationEnrichment, + taskQueue: 'organizations-enrichment', + workflowExecutionTimeout: '5 minutes', + }, + }) + } catch (err) { + if (err instanceof ScheduleAlreadyRunning) { + svc.log.info('Schedule already registered in Temporal.') + svc.log.info('Configuration may have changed since. Please make sure they are in sync.') + } else { + throw new Error(err) + } + } +} diff --git a/services/apps/premium/organizations_enrichment_worker/src/types/common.ts b/services/apps/premium/organizations_enrichment_worker/src/types/common.ts new file mode 100644 index 0000000000..c6bd5d8ac6 --- /dev/null +++ b/services/apps/premium/organizations_enrichment_worker/src/types/common.ts @@ -0,0 +1,7 @@ +import { PlatformType } from '@crowd/types' + +export const ENRICHMENT_PLATFORM_PRIORITY = [ + PlatformType.GITHUB, + PlatformType.LINKEDIN, + PlatformType.TWITTER, +] diff --git a/services/apps/premium/organizations_enrichment_worker/src/workflows.ts b/services/apps/premium/organizations_enrichment_worker/src/workflows.ts new file mode 100644 index 0000000000..0d0a038717 --- /dev/null +++ b/services/apps/premium/organizations_enrichment_worker/src/workflows.ts @@ -0,0 +1,5 @@ +import { triggerTenantOrganizationEnrichment } from './workflows/triggerTenantOrganizationEnrichment' +import { enrichTenantOrganizations } from './workflows/entrichTenantOrganizations' +import { enrichOrganization } from './workflows/enrichOrganization' + +export { triggerTenantOrganizationEnrichment, enrichTenantOrganizations, enrichOrganization } diff --git a/services/apps/premium/organizations_enrichment_worker/src/workflows/enrichOrganization.ts b/services/apps/premium/organizations_enrichment_worker/src/workflows/enrichOrganization.ts new file mode 100644 index 0000000000..d61eeaa5fc --- /dev/null +++ b/services/apps/premium/organizations_enrichment_worker/src/workflows/enrichOrganization.ts @@ -0,0 +1,24 @@ +import { proxyActivities } from '@temporalio/workflow' +import * as activities from '../activities/organizationEnrichment' +import { TenantPlans } from '@crowd/types' + +const { tryEnrichOrganization, incrementTenantCredits, syncToOpensearch } = proxyActivities< + typeof activities +>({ + startToCloseTimeout: '75 seconds', +}) + +export interface IEnrichOrganizationInput { + organizationId: string + tenantId: string + plan: TenantPlans +} + +export async function enrichOrganization(input: IEnrichOrganizationInput): Promise { + const wasEnriched = await tryEnrichOrganization(input.tenantId, input.organizationId) + + if (wasEnriched) { + await syncToOpensearch(input.tenantId, input.organizationId) + await incrementTenantCredits(input.tenantId, input.plan) + } +} diff --git a/services/apps/premium/organizations_enrichment_worker/src/workflows/entrichTenantOrganizations.ts b/services/apps/premium/organizations_enrichment_worker/src/workflows/entrichTenantOrganizations.ts new file mode 100644 index 0000000000..1be4a1606e --- /dev/null +++ b/services/apps/premium/organizations_enrichment_worker/src/workflows/entrichTenantOrganizations.ts @@ -0,0 +1,74 @@ +import { IPremiumTenantInfo } from '../repos/tenant.repo' +import * as activities from '../activities/organizationEnrichment' +import { + ChildWorkflowCancellationType, + ParentClosePolicy, + proxyActivities, + startChild, +} from '@temporalio/workflow' +import { enrichOrganization } from './enrichOrganization' + +const { getRemainingTenantCredits, getTenantOrganizationsForEnrichment } = proxyActivities< + typeof activities +>({ + startToCloseTimeout: '75 seconds', +}) + +const BATCH_SIZE = 100 + +export async function enrichTenantOrganizations(tenant: IPremiumTenantInfo): Promise { + // check how many credits the tenant has left + // this will be our limit (1 credit = 1 enriched organization) + let remainingCredits = await getRemainingTenantCredits(tenant) + + if (remainingCredits === 0) { + // we have no credits left on this tenant + return + } + + let page = 1 + while (remainingCredits > 0) { + const batchSize = Math.min(remainingCredits, BATCH_SIZE) + // get organizations that should be enriched + const organizationIds = await getTenantOrganizationsForEnrichment(tenant.id, batchSize, page) + + if (organizationIds.length === 0) { + // no more organizations to enrich + return + } + + // trigger enrichment workflow + const promises = [] + for (const organizationId of organizationIds) { + promises.push( + startChild(enrichOrganization, { + workflowId: 'enrich-organization/' + organizationId, + cancellationType: ChildWorkflowCancellationType.ABANDON, + parentClosePolicy: ParentClosePolicy.PARENT_CLOSE_POLICY_ABANDON, + workflowExecutionTimeout: '15 minutes', + retry: { + backoffCoefficient: 2, + maximumAttempts: 10, + initialInterval: 2 * 1000, + maximumInterval: 30 * 1000, + }, + args: [ + { + organizationId, + tenantId: tenant.id, + plan: tenant.plan, + }, + ], + searchAttributes: { + TenantId: [tenant.id], + }, + }), + ) + remainingCredits-- + } + + await Promise.all(promises) + + page++ + } +} diff --git a/services/apps/premium/organizations_enrichment_worker/src/workflows/triggerTenantOrganizationEnrichment.ts b/services/apps/premium/organizations_enrichment_worker/src/workflows/triggerTenantOrganizationEnrichment.ts new file mode 100644 index 0000000000..f47b123cb0 --- /dev/null +++ b/services/apps/premium/organizations_enrichment_worker/src/workflows/triggerTenantOrganizationEnrichment.ts @@ -0,0 +1,52 @@ +import { + ChildWorkflowCancellationType, + ParentClosePolicy, + proxyActivities, + startChild, +} from '@temporalio/workflow' +import * as activities from '../activities/organizationEnrichment' +import { enrichTenantOrganizations } from './entrichTenantOrganizations' + +const { getApplicableTenants, hasTenantOrganizationEnrichmentEnabled } = proxyActivities< + typeof activities +>({ + startToCloseTimeout: '75 seconds', +}) + +export async function triggerTenantOrganizationEnrichment(): Promise { + const perPage = 100 + // get tenants that are applicable for organization enrichment + let tenants = await getApplicableTenants(perPage) + while (tenants.length > 0) { + const tenantsEnabled = await Promise.all( + tenants.map((t) => hasTenantOrganizationEnrichmentEnabled(t.id)), + ) + const enabledTenants = tenants.filter((_, i) => tenantsEnabled[i]) + if (enabledTenants.length > 0) { + // trigger tenant organization enrichment for each tenant + await Promise.all( + enabledTenants.map((tenant) => { + return startChild(enrichTenantOrganizations, { + workflowId: 'tenant-organizations-enrichment/' + tenant.id, + cancellationType: ChildWorkflowCancellationType.ABANDON, + parentClosePolicy: ParentClosePolicy.PARENT_CLOSE_POLICY_ABANDON, + workflowExecutionTimeout: '15 minutes', + retry: { + backoffCoefficient: 2, + maximumAttempts: 10, + initialInterval: 2 * 1000, + maximumInterval: 30 * 1000, + }, + args: [tenant], + searchAttributes: { + TenantId: [tenant.id], + }, + }) + }), + ) + } + + // load next page of applicable tenants + tenants = await getApplicableTenants(perPage, tenants[tenants.length - 1].id) + } +} diff --git a/services/apps/premium/organizations_enrichment_worker/tsconfig.json b/services/apps/premium/organizations_enrichment_worker/tsconfig.json new file mode 100644 index 0000000000..bf5ba4932d --- /dev/null +++ b/services/apps/premium/organizations_enrichment_worker/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "target": "es2017", + "module": "Node16", + "lib": ["es6", "es7", "es2017", "es2017.object", "es2015.promise"], + "skipLibCheck": true, + "sourceMap": true, + "moduleResolution": "node16", + "experimentalDecorators": true, + "esModuleInterop": true, + "baseUrl": "./src", + "paths": { + "@crowd/*/premium": ["../../../../libs/*/src/premium"], + "@crowd/*": ["../../../../libs/*/src"], + "@crowd/archetype-*": ["../../../../archetypes/*/src"] + } + }, + "include": ["src/**/*"] +} diff --git a/services/apps/profiles_worker/.eslintrc.cjs b/services/apps/profiles_worker/.eslintrc.cjs new file mode 100644 index 0000000000..25ba4e0d66 --- /dev/null +++ b/services/apps/profiles_worker/.eslintrc.cjs @@ -0,0 +1,21 @@ +module.exports = { + parser: '@typescript-eslint/parser', + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:prettier/recommended', + ], + plugins: ['@typescript-eslint', 'prettier'], + parserOptions: { + ecmaVersion: 2022, + sourceType: 'module', + }, + env: { + es6: true, + node: true, + }, + rules: { + 'prettier/prettier': 'error', + '@typescript-eslint/explicit-module-boundary-types': 'off', + }, +} diff --git a/services/apps/profiles_worker/.prettierignore b/services/apps/profiles_worker/.prettierignore new file mode 100644 index 0000000000..2b24877309 --- /dev/null +++ b/services/apps/profiles_worker/.prettierignore @@ -0,0 +1,3 @@ +dist/ +.eslintrc.cjs +.prettierrc.cjs diff --git a/services/apps/profiles_worker/.prettierrc.cjs b/services/apps/profiles_worker/.prettierrc.cjs new file mode 100644 index 0000000000..a8ca459839 --- /dev/null +++ b/services/apps/profiles_worker/.prettierrc.cjs @@ -0,0 +1,7 @@ +module.exports = { + singleQuote: true, + arrowParens: 'always', + printWidth: 100, + trailingComma: 'all', + semi: false, +} diff --git a/services/apps/profiles_worker/package.json b/services/apps/profiles_worker/package.json new file mode 100644 index 0000000000..f28772b071 --- /dev/null +++ b/services/apps/profiles_worker/package.json @@ -0,0 +1,36 @@ +{ + "name": "@crowd/profiles-worker", + "version": "1.0.0", + "private": true, + "scripts": { + "start": "CROWD_TEMPORAL_TASKQUEUE=profiles SERVICE=profiles-worker TS_NODE_TRANSPILE_ONLY=true node -r tsconfig-paths/register -r ts-node/register src/main.ts", + "start:debug:local": "set -a && . ../../../backend/.env.dist.local && . ../../../backend/.env.override.local && set +a && CROWD_TEMPORAL_TASKQUEUE=profiles SERVICE=profiles-worker TS_NODE_TRANSPILE_ONLY=true LOG_LEVEL=trace node --inspect=0.0.0.0:9232 -r tsconfig-paths/register -r ts-node/register src/main.ts", + "start:debug": "CROWD_TEMPORAL_TASKQUEUE=profiles SERVICE=profiles-worker TS_NODE_TRANSPILE_ONLY=true LOG_LEVEL=trace node --inspect=0.0.0.0:9232 -r tsconfig-paths/register -r ts-node/register src/main.ts", + "dev:local": "./node_modules/.bin/nodemon --watch src --watch ../../libs --ext ts --exec pnpm run start:debug:local", + "dev": "./node_modules/.bin/nodemon --watch src --watch ../../libs --ext ts --exec pnpm run start:debug", + "lint": "./node_modules/.bin/eslint --ext .ts src --max-warnings=0", + "format": "./node_modules/.bin/prettier --write \"src/**/*.ts\"", + "format-check": "./node_modules/.bin/prettier --check .", + "tsc-check": "./node_modules/.bin/tsc --noEmit" + }, + "dependencies": { + "@crowd/archetype-standard": "file:../../archetypes/standard", + "@crowd/archetype-worker": "file:../../archetypes/worker", + "@crowd/types": "file:../../libs/types", + "@temporalio/workflow": "~1.8.6", + "ts-node": "^10.9.1", + "tsconfig-paths": "^4.2.0", + "typescript": "^5.2.2" + }, + "devDependencies": { + "@types/node": "^20.8.2", + "@types/uuid": "~9.0.6", + "@typescript-eslint/eslint-plugin": "^6.7.4", + "@typescript-eslint/parser": "^6.7.4", + "eslint": "^8.50.0", + "eslint-config-prettier": "^9.0.0", + "eslint-plugin-prettier": "^5.0.0", + "nodemon": "^3.0.1", + "prettier": "^3.0.3" + } +} diff --git a/services/apps/profiles_worker/src/activities.ts b/services/apps/profiles_worker/src/activities.ts new file mode 100644 index 0000000000..be231964e8 --- /dev/null +++ b/services/apps/profiles_worker/src/activities.ts @@ -0,0 +1,3 @@ +import { updateMemberAffiliations } from './activities/member/memberUpdate' + +export { updateMemberAffiliations } diff --git a/services/apps/profiles_worker/src/activities/member/memberUpdate.ts b/services/apps/profiles_worker/src/activities/member/memberUpdate.ts new file mode 100644 index 0000000000..a9cf0aba47 --- /dev/null +++ b/services/apps/profiles_worker/src/activities/member/memberUpdate.ts @@ -0,0 +1,57 @@ +import { svc } from '../../main' +import { MemberWithIDOnly } from '../../types/member' + +/* +updateMemberAffiliations is a Temporal activity that updates all affiliations for +a given member. +*/ +export async function updateMemberAffiliations(input: MemberWithIDOnly): Promise { + try { + await svc.postgres.writer.connection().query( + `WITH new_activities_organizations AS ( + SELECT + a.id, + + -- this 000000 magic is to differentiate between nothing to LEFT JOIN with and real individial affiliation + -- we want to keep NULL in 'organizationId' if there is an affiliation configured, + -- but if there is no manual affiliation, we know this by 'msa.id' being NULL, and then using 000000 as a marker, + -- which we remove afterwards + (ARRAY_REMOVE(ARRAY_AGG(CASE WHEN msa.id IS NULL THEN '00000000-0000-0000-0000-000000000000' ELSE msa."organizationId" END), '00000000-0000-0000-0000-000000000000') + || ARRAY_REMOVE(ARRAY_AGG(mo."organizationId" ORDER BY mo."dateStart" DESC, mo.id), NULL) + || ARRAY_REMOVE(ARRAY_AGG(mo1."organizationId" ORDER BY mo1."createdAt" DESC, mo1.id), NULL) + || ARRAY_REMOVE(ARRAY_AGG(mo2."organizationId" ORDER BY mo2."createdAt", mo2.id), NULL) + )[1] AS new_org + FROM activities a + LEFT JOIN "memberSegmentAffiliations" msa ON msa."memberId" = a."memberId" AND a."segmentId" = msa."segmentId" AND ( + a.timestamp BETWEEN msa."dateStart" AND msa."dateEnd" + OR (a.timestamp >= msa."dateStart" AND msa."dateEnd" IS NULL) + ) + LEFT JOIN "memberOrganizations" mo ON mo."memberId" = a."memberId" + AND ( + a.timestamp BETWEEN mo."dateStart" AND mo."dateEnd" + OR (a.timestamp >= mo."dateStart" AND mo."dateEnd" IS NULL) + ) + AND mo."deletedAt" IS NULL + LEFT JOIN "memberOrganizations" mo1 ON mo1."memberId" = a."memberId" + AND mo1."dateStart" IS NULL AND mo1."dateEnd" IS NULL + AND mo1."createdAt" <= a.timestamp + AND mo1."deletedAt" IS NULL + LEFT JOIN "memberOrganizations" mo2 ON mo2."memberId" = a."memberId" + AND mo2."dateStart" IS NULL AND mo2."dateEnd" IS NULL + AND mo2."deletedAt" IS NULL + WHERE a."memberId" = $1 + GROUP BY a.id + ) + UPDATE activities a1 + SET "organizationId" = nao.new_org + FROM new_activities_organizations nao + WHERE a1.id = nao.id + AND ("organizationId" != nao.new_org + OR ("organizationId" IS NULL AND nao.new_org IS NOT NULL) + OR ("organizationId" IS NOT NULL AND nao.new_org IS NULL));`, + [input.member.id], + ) + } catch (err) { + throw new Error(err) + } +} diff --git a/services/apps/profiles_worker/src/main.ts b/services/apps/profiles_worker/src/main.ts new file mode 100644 index 0000000000..27896e9f9a --- /dev/null +++ b/services/apps/profiles_worker/src/main.ts @@ -0,0 +1,31 @@ +import { Config } from '@crowd/archetype-standard' +import { ServiceWorker, Options } from '@crowd/archetype-worker' + +const config: Config = { + producer: { + enabled: false, + }, + temporal: { + enabled: true, + }, + redis: { + enabled: false, + }, +} + +const options: Options = { + postgres: { + enabled: true, + }, + opensearch: { + enabled: false, + }, +} + +export const svc = new ServiceWorker(config, options) + +setImmediate(async () => { + await svc.init() + + await svc.start() +}) diff --git a/services/apps/profiles_worker/src/types/member.ts b/services/apps/profiles_worker/src/types/member.ts new file mode 100644 index 0000000000..74e210924d --- /dev/null +++ b/services/apps/profiles_worker/src/types/member.ts @@ -0,0 +1,5 @@ +export interface MemberWithIDOnly { + member: { + id: string + } +} diff --git a/services/apps/profiles_worker/src/workflows.ts b/services/apps/profiles_worker/src/workflows.ts new file mode 100644 index 0000000000..233f128fb7 --- /dev/null +++ b/services/apps/profiles_worker/src/workflows.ts @@ -0,0 +1,3 @@ +import { memberUpdate } from './workflows/member/memberUpdate' + +export { memberUpdate } diff --git a/services/apps/profiles_worker/src/workflows/member/memberUpdate.ts b/services/apps/profiles_worker/src/workflows/member/memberUpdate.ts new file mode 100644 index 0000000000..3c022af415 --- /dev/null +++ b/services/apps/profiles_worker/src/workflows/member/memberUpdate.ts @@ -0,0 +1,21 @@ +import { proxyActivities } from '@temporalio/workflow' + +import * as activities from '../../activities' +import { MemberWithIDOnly } from '../../types/member' + +// Configure timeouts and retry policies to update a member in the database. +const { updateMemberAffiliations } = proxyActivities({ + startToCloseTimeout: '60 seconds', +}) + +/* +memberUpdate is a Temporal workflow that: + - [Activity]: Update all affiliations for a given member in the database. +*/ +export async function memberUpdate(input: MemberWithIDOnly): Promise { + try { + await updateMemberAffiliations(input) + } catch (err) { + throw new Error(err) + } +} diff --git a/services/apps/profiles_worker/tsconfig.json b/services/apps/profiles_worker/tsconfig.json new file mode 100644 index 0000000000..47a983b5d5 --- /dev/null +++ b/services/apps/profiles_worker/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "target": "es2017", + "module": "Node16", + "lib": ["es6", "es7", "es2017", "es2017.object", "es2015.promise"], + "skipLibCheck": true, + "sourceMap": true, + "moduleResolution": "node16", + "experimentalDecorators": true, + "esModuleInterop": true, + "baseUrl": "./src", + "paths": { + "@crowd/*": ["../../../libs/*/src"], + "@crowd/archetype-*": ["../../../archetypes/*/src"] + } + }, + "include": ["src/**/*"] +} diff --git a/services/apps/search_sync_worker/config/custom-environment-variables.json b/services/apps/search_sync_worker/config/custom-environment-variables.json index 5d53ec56f9..4afd4ad866 100644 --- a/services/apps/search_sync_worker/config/custom-environment-variables.json +++ b/services/apps/search_sync_worker/config/custom-environment-variables.json @@ -1,6 +1,7 @@ { "service": { - "edition": "CROWD_EDITION" + "edition": "CROWD_EDITION", + "queuePriorityLevel": "QUEUE_PRIORITY_LEVEL" }, "db": { "host": "CROWD_DB_WRITE_HOST", diff --git a/services/apps/search_sync_worker/config/default.json b/services/apps/search_sync_worker/config/default.json index 0ae2ffe715..c3476f4311 100644 --- a/services/apps/search_sync_worker/config/default.json +++ b/services/apps/search_sync_worker/config/default.json @@ -1,5 +1,7 @@ { - "service": {}, + "service": { + "queuePriorityLevel": "normal" + }, "db": {}, "sqs": {}, "redis": {}, diff --git a/services/apps/search_sync_worker/package.json b/services/apps/search_sync_worker/package.json index fdf3bc5ba6..23752a571c 100644 --- a/services/apps/search_sync_worker/package.json +++ b/services/apps/search_sync_worker/package.json @@ -22,6 +22,7 @@ "script:sync-tenant-members": "SERVICE=script TS_NODE_TRANSPILE_ONLY=true node -r tsconfig-paths/register -r ts-node/register src/bin/sync-tenant-members.ts", "script:sync-tenant-activities": "SERVICE=script TS_NODE_TRANSPILE_ONLY=true node -r tsconfig-paths/register -r ts-node/register src/bin/sync-tenant-activities.ts", "script:sync-tenant-organizations": "SERVICE=script TS_NODE_TRANSPILE_ONLY=true node -r tsconfig-paths/register -r ts-node/register src/bin/sync-tenant-organizations.ts", + "script:cleanup-organization": "SERVICE=script TS_NODE_TRANSPILE_ONLY=true node -r tsconfig-paths/register -r ts-node/register src/bin/cleanup-organization.ts", "script:cleanup-tenant-members": "SERVICE=script TS_NODE_TRANSPILE_ONLY=true node -r tsconfig-paths/register -r ts-node/register src/bin/cleanup-tenant-members.ts", "script:cleanup-tenant-activities": "SERVICE=script TS_NODE_TRANSPILE_ONLY=true node -r tsconfig-paths/register -r ts-node/register src/bin/cleanup-tenant-activities.ts", "script:cleanup-tenant-organizations": "SERVICE=script TS_NODE_TRANSPILE_ONLY=true node -r tsconfig-paths/register -r ts-node/register src/bin/cleanup-tenant-organizations.ts", diff --git a/services/apps/search_sync_worker/src/bin/cleanup-organization.ts b/services/apps/search_sync_worker/src/bin/cleanup-organization.ts new file mode 100644 index 0000000000..a2a8312f3c --- /dev/null +++ b/services/apps/search_sync_worker/src/bin/cleanup-organization.ts @@ -0,0 +1,28 @@ +import { DB_CONFIG, OPENSEARCH_CONFIG, SERVICE_CONFIG } from '../conf' +import { OpenSearchService, OrganizationSyncService } from '@crowd/opensearch' +import { DbStore, getDbConnection } from '@crowd/database' +import { getServiceLogger } from '@crowd/logging' + +const log = getServiceLogger() + +const processArguments = process.argv.slice(2) + +if (processArguments.length !== 1) { + log.error('Expected 1 argument: organizationId') + process.exit(1) +} + +const organizationId = processArguments[0] + +setImmediate(async () => { + const openSearchService = new OpenSearchService(log, OPENSEARCH_CONFIG()) + + const dbConnection = await getDbConnection(DB_CONFIG()) + const store = new DbStore(log, dbConnection) + + const service = new OrganizationSyncService(store, openSearchService, log, SERVICE_CONFIG()) + + await service.removeOrganization(organizationId) + + process.exit(0) +}) diff --git a/services/apps/search_sync_worker/src/conf/index.ts b/services/apps/search_sync_worker/src/conf/index.ts index a02ea34892..e1fd1a5428 100644 --- a/services/apps/search_sync_worker/src/conf/index.ts +++ b/services/apps/search_sync_worker/src/conf/index.ts @@ -1,6 +1,7 @@ import { IDatabaseConfig } from '@crowd/database' import { IRedisConfiguration } from '@crowd/redis' import { ISqsClientConfig } from '@crowd/sqs' +import { QueuePriorityLevel } from '@crowd/types' import config from 'config' export interface IOpenSearchConfig { @@ -12,6 +13,7 @@ export interface IOpenSearchConfig { export interface IServiceConfig { edition: string + queuePriorityLevel: QueuePriorityLevel } let serviceConfig: IServiceConfig diff --git a/services/apps/search_sync_worker/src/main.ts b/services/apps/search_sync_worker/src/main.ts index 94b9ecd109..4e37d61a9c 100644 --- a/services/apps/search_sync_worker/src/main.ts +++ b/services/apps/search_sync_worker/src/main.ts @@ -4,7 +4,7 @@ import { getServiceTracer } from '@crowd/tracing' import { getServiceLogger } from '@crowd/logging' import { getRedisClient } from '@crowd/redis' import { getSqsClient } from '@crowd/sqs' -import { DB_CONFIG, OPENSEARCH_CONFIG, REDIS_CONFIG, SQS_CONFIG } from './conf' +import { DB_CONFIG, OPENSEARCH_CONFIG, REDIS_CONFIG, SERVICE_CONFIG, SQS_CONFIG } from './conf' import { WorkerQueueReceiver } from './queue' const tracer = getServiceTracer() @@ -24,6 +24,7 @@ setImmediate(async () => { const dbConnection = await getDbConnection(DB_CONFIG(), MAX_CONCURRENT_PROCESSING) const worker = new WorkerQueueReceiver( + SERVICE_CONFIG().queuePriorityLevel, redis, sqsClient, dbConnection, diff --git a/services/apps/search_sync_worker/src/queue/index.ts b/services/apps/search_sync_worker/src/queue/index.ts index f732a2c7dd..a3a9a51233 100644 --- a/services/apps/search_sync_worker/src/queue/index.ts +++ b/services/apps/search_sync_worker/src/queue/index.ts @@ -1,25 +1,30 @@ import { BatchProcessor } from '@crowd/common' -import { Tracer, Span, SpanStatusCode } from '@crowd/tracing' import { DbConnection, DbStore } from '@crowd/database' import { Logger } from '@crowd/logging' +import { RedisClient } from '@crowd/redis' +import { + SEARCH_SYNC_WORKER_QUEUE_SETTINGS, + SqsClient, + SqsPrioritizedQueueReciever, +} from '@crowd/sqs' +import { Span, SpanStatusCode, Tracer } from '@crowd/tracing' +import { IQueueMessage, QueuePriorityLevel, SearchSyncWorkerQueueMessageType } from '@crowd/types' import { OpenSearchService, ActivitySyncService, MemberSyncService, OrganizationSyncService, } from '@crowd/opensearch' -import { RedisClient } from '@crowd/redis' -import { SEARCH_SYNC_WORKER_QUEUE_SETTINGS, SqsClient, SqsQueueReceiver } from '@crowd/sqs' -import { IQueueMessage, SearchSyncWorkerQueueMessageType } from '@crowd/types' -import { SERVICE_CONFIG } from 'conf' +import { SERVICE_CONFIG } from '../conf' /* eslint-disable @typescript-eslint/no-explicit-any */ -export class WorkerQueueReceiver extends SqsQueueReceiver { +export class WorkerQueueReceiver extends SqsPrioritizedQueueReciever { private readonly memberBatchProcessor: BatchProcessor private readonly activityBatchProcessor: BatchProcessor private readonly organizationBatchProcessor: BatchProcessor constructor( + level: QueuePriorityLevel, private readonly redisClient: RedisClient, client: SqsClient, private readonly dbConn: DbConnection, @@ -29,6 +34,7 @@ export class WorkerQueueReceiver extends SqsQueueReceiver { maxConcurrentProcessing: number, ) { super( + level, client, SEARCH_SYNC_WORKER_QUEUE_SETTINGS, maxConcurrentProcessing, @@ -112,7 +118,7 @@ export class WorkerQueueReceiver extends SqsQueueReceiver { ) } - protected override async processMessage(message: T): Promise { + public override async processMessage(message: T): Promise { await this.tracer.startActiveSpan('ProcessMessage', async (span: Span) => { try { this.log.trace({ messageType: message.type }, 'Processing message!') diff --git a/services/apps/template_worker/src/main.ts b/services/apps/template_worker/src/main.ts index 90fe142c39..3ba48abab3 100644 --- a/services/apps/template_worker/src/main.ts +++ b/services/apps/template_worker/src/main.ts @@ -18,6 +18,9 @@ const options: Options = { postgres: { enabled: false, }, + opensearch: { + enabled: false, + }, } const svc = new ServiceWorker(config, options) diff --git a/services/apps/webhook_api/config/custom-environment-variables.json b/services/apps/webhook_api/config/custom-environment-variables.json index 5f249ff8dc..322bb4daa7 100644 --- a/services/apps/webhook_api/config/custom-environment-variables.json +++ b/services/apps/webhook_api/config/custom-environment-variables.json @@ -12,5 +12,15 @@ "port": "CROWD_SQS_PORT", "accessKeyId": "CROWD_SQS_AWS_ACCESS_KEY_ID", "secretAccessKey": "CROWD_SQS_AWS_SECRET_ACCESS_KEY" + }, + "unleash": { + "url": "CROWD_UNLEASH_URL", + "apiKey": "CROWD_UNLEASH_BACKEND_API_KEY" + }, + "redis": { + "username": "CROWD_REDIS_USERNAME", + "password": "CROWD_REDIS_PASSWORD", + "host": "CROWD_REDIS_HOST", + "port": "CROWD_REDIS_PORT" } } diff --git a/services/apps/webhook_api/config/default.json b/services/apps/webhook_api/config/default.json index 371dfadee0..8559154b27 100644 --- a/services/apps/webhook_api/config/default.json +++ b/services/apps/webhook_api/config/default.json @@ -2,6 +2,8 @@ "service": { "port": 8082 }, + "unleash": {}, + "redis": {}, "db": {}, "sqs": {} } diff --git a/services/apps/webhook_api/package.json b/services/apps/webhook_api/package.json index 752589f8fd..673137c245 100644 --- a/services/apps/webhook_api/package.json +++ b/services/apps/webhook_api/package.json @@ -21,6 +21,9 @@ "@crowd/sqs": "file:../../libs/sqs", "@crowd/types": "file:../../libs/types", "@crowd/telemetry": "file:../../libs/telemetry", + "@crowd/feature-flags": "file:../../libs/feature-flags", + "@crowd/common_services": "file:../../libs/common_services", + "@crowd/redis": "file:../../libs/redis", "@types/config": "^3.3.0", "@types/express": "^4.17.17", "@types/node": "^18.16.3", diff --git a/services/apps/webhook_api/src/conf/index.ts b/services/apps/webhook_api/src/conf/index.ts index 5d80e76b15..f2105d97b0 100644 --- a/services/apps/webhook_api/src/conf/index.ts +++ b/services/apps/webhook_api/src/conf/index.ts @@ -1,7 +1,9 @@ import { IDatabaseConfig } from '@crowd/database' import { ISqsClientConfig } from '@crowd/sqs' import config from 'config' - +import { IUnleashConfig } from '@crowd/feature-flags' +import { SERVICE } from '@crowd/common' +import { IRedisConfiguration } from '@crowd/redis' export interface IWebhookApiServiceConfig { port: number } @@ -29,3 +31,20 @@ export const DB_CONFIG = (): IDatabaseConfig => { dbConfig = config.get('db') return dbConfig } + +let unleashConfig: IUnleashConfig | undefined +export const UNLEASH_CONFIG = (): IUnleashConfig | undefined => { + if (unleashConfig) return unleashConfig + + unleashConfig = Object.assign({ appName: SERVICE }, config.get('unleash')) + + return unleashConfig +} + +let redisConfig: IRedisConfiguration +export const REDIS_CONFIG = (): IRedisConfiguration => { + if (redisConfig) return redisConfig + + redisConfig = config.get('redis') + return redisConfig +} diff --git a/services/apps/webhook_api/src/main.ts b/services/apps/webhook_api/src/main.ts index 3ca3dd16e4..8d1535a8ef 100644 --- a/services/apps/webhook_api/src/main.ts +++ b/services/apps/webhook_api/src/main.ts @@ -1,9 +1,9 @@ import { getServiceLogger } from '@crowd/logging' -import { DB_CONFIG, SQS_CONFIG, WEBHOOK_API_CONFIG } from './conf' +import { DB_CONFIG, REDIS_CONFIG, SQS_CONFIG, UNLEASH_CONFIG, WEBHOOK_API_CONFIG } from './conf' import express from 'express' import { loggingMiddleware } from './middleware/logging' import { getSqsClient } from '@crowd/sqs' -import { getDbConnection } from '@crowd/database' +import { DbStore, getDbConnection } from '@crowd/database' import { databaseMiddleware } from './middleware/database' import { errorMiddleware } from './middleware/error' import { sqsMiddleware } from './middleware/sqs' @@ -12,17 +12,46 @@ import { installGroupsIoRoutes } from './routes/groupsio' import { installDiscourseRoutes } from './routes/discourse' import cors from 'cors' import { telemetryExpressMiddleware } from '@crowd/telemetry' +import { getUnleashClient } from '@crowd/feature-flags' +import { getRedisClient } from '@crowd/redis' +import { + IntegrationStreamWorkerEmitter, + PriorityLevelContextRepository, + QueuePriorityContextLoader, +} from '@crowd/common_services' +import { getServiceTracer } from '@crowd/tracing' +import { emittersMiddleware } from './middleware/emitters' +const tracer = getServiceTracer() const log = getServiceLogger() const config = WEBHOOK_API_CONFIG() setImmediate(async () => { const app = express() + const unleash = await getUnleashClient(UNLEASH_CONFIG()) + + const redisClient = await getRedisClient(REDIS_CONFIG()) + const sqsClient = getSqsClient(SQS_CONFIG()) const dbConnection = await getDbConnection(DB_CONFIG(), 3, 0) + const priorityLevelRepo = new PriorityLevelContextRepository(new DbStore(log, dbConnection), log) + const loader: QueuePriorityContextLoader = (tenantId: string) => + priorityLevelRepo.loadPriorityLevelContext(tenantId) + + const integrationStreamWorkerEmitter = new IntegrationStreamWorkerEmitter( + sqsClient, + redisClient, + tracer, + unleash, + loader, + log, + ) + + await integrationStreamWorkerEmitter.init() + app.use(emittersMiddleware(integrationStreamWorkerEmitter)) app.use((req, res, next) => { // Groups.io doesn't send a content-type header, // so request body parsing is just skipped diff --git a/services/apps/webhook_api/src/middleware/emitters.ts b/services/apps/webhook_api/src/middleware/emitters.ts new file mode 100644 index 0000000000..f6a5e87f7e --- /dev/null +++ b/services/apps/webhook_api/src/middleware/emitters.ts @@ -0,0 +1,21 @@ +import { IntegrationStreamWorkerEmitter } from '@crowd/common_services' +import { NextFunction, Request, RequestHandler, Response } from 'express' + +export interface IEmittersRequest { + emitters: { + integrationStreamWorker: IntegrationStreamWorkerEmitter + } +} + +export const emittersMiddleware = ( + integrationStreamWorker: IntegrationStreamWorkerEmitter, +): RequestHandler => { + return (req: Request, _res: Response, next: NextFunction) => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + ;(req as any).emitters = { + integrationStreamWorker, + } + + next() + } +} diff --git a/services/apps/webhook_api/src/middleware/index.ts b/services/apps/webhook_api/src/middleware/index.ts index 0ffa59e487..0303134d7b 100644 --- a/services/apps/webhook_api/src/middleware/index.ts +++ b/services/apps/webhook_api/src/middleware/index.ts @@ -2,5 +2,11 @@ import { Request } from 'express' import { ILoggingRequest } from './logging' import { IDatabaseRequest } from './database' import { ISqsRequest } from './sqs' +import { IEmittersRequest } from './emitters' -export interface ApiRequest extends Request, ILoggingRequest, IDatabaseRequest, ISqsRequest {} +export interface ApiRequest + extends Request, + ILoggingRequest, + IDatabaseRequest, + ISqsRequest, + IEmittersRequest {} diff --git a/services/apps/webhook_api/src/routes/discourse.ts b/services/apps/webhook_api/src/routes/discourse.ts index 6d30a7467d..ce62b628c6 100644 --- a/services/apps/webhook_api/src/routes/discourse.ts +++ b/services/apps/webhook_api/src/routes/discourse.ts @@ -1,16 +1,11 @@ -import { asyncWrap } from '../middleware/error' -import { WebhooksRepository } from '../repos/webhooks.repo' import { Error400BadRequest } from '@crowd/common' -import { getServiceTracer } from '@crowd/tracing' -import { IntegrationStreamWorkerEmitter } from '@crowd/sqs' import { PlatformType, WebhookType } from '@crowd/types' import express from 'express' import { verifyWebhookSignature } from 'utils/crypto' - -const tracer = getServiceTracer() +import { asyncWrap } from '../middleware/error' +import { WebhooksRepository } from '../repos/webhooks.repo' export const installDiscourseRoutes = async (app: express.Express) => { - let emitter: IntegrationStreamWorkerEmitter app.post( '/discourse/:tenantId/', asyncWrap(async (req, res) => { @@ -59,12 +54,11 @@ export const installDiscourseRoutes = async (app: express.Express) => { }, ) - if (!emitter) { - emitter = new IntegrationStreamWorkerEmitter(req.sqs, tracer, req.log) - await emitter.init() - } - - await emitter.triggerWebhookProcessing(integration.tenantId, integration.platform, id) + await req.emitters.integrationStreamWorker.triggerWebhookProcessing( + integration.tenantId, + integration.platform, + id, + ) res.sendStatus(204) } else { diff --git a/services/apps/webhook_api/src/routes/github.ts b/services/apps/webhook_api/src/routes/github.ts index dd11f442bc..e1f1f09619 100644 --- a/services/apps/webhook_api/src/routes/github.ts +++ b/services/apps/webhook_api/src/routes/github.ts @@ -1,18 +1,13 @@ import { asyncWrap } from '../middleware/error' import { WebhooksRepository } from '../repos/webhooks.repo' import { Error400BadRequest } from '@crowd/common' -import { getServiceTracer } from '@crowd/tracing' -import { IntegrationStreamWorkerEmitter } from '@crowd/sqs' import { PlatformType, WebhookType } from '@crowd/types' import express from 'express' -const tracer = getServiceTracer() - const SIGNATURE_HEADER = 'x-hub-signature' const EVENT_HEADER = 'x-github-event' export const installGithubRoutes = async (app: express.Express) => { - let emitter: IntegrationStreamWorkerEmitter app.post( '/github', asyncWrap(async (req, res) => { @@ -48,12 +43,11 @@ export const installGithubRoutes = async (app: express.Express) => { }, ) - if (!emitter) { - emitter = new IntegrationStreamWorkerEmitter(req.sqs, tracer, req.log) - await emitter.init() - } - - await emitter.triggerWebhookProcessing(integration.tenantId, integration.platform, id) + await req.emitters.integrationStreamWorker.triggerWebhookProcessing( + integration.tenantId, + integration.platform, + id, + ) res.sendStatus(204) } else { diff --git a/services/apps/webhook_api/src/routes/groupsio.ts b/services/apps/webhook_api/src/routes/groupsio.ts index 6d3c635329..261db7a3bf 100644 --- a/services/apps/webhook_api/src/routes/groupsio.ts +++ b/services/apps/webhook_api/src/routes/groupsio.ts @@ -1,15 +1,10 @@ import { asyncWrap } from '../middleware/error' import { WebhooksRepository } from '../repos/webhooks.repo' import { Error400BadRequest } from '@crowd/common' -import { getServiceTracer } from '@crowd/tracing' -import { IntegrationStreamWorkerEmitter } from '@crowd/sqs' import { WebhookType } from '@crowd/types' import express from 'express' -const tracer = getServiceTracer() - export const installGroupsIoRoutes = async (app: express.Express) => { - let emitter: IntegrationStreamWorkerEmitter app.post( '/groupsio', asyncWrap(async (req, res) => { @@ -42,12 +37,11 @@ export const installGroupsIoRoutes = async (app: express.Express) => { }, ) - if (!emitter) { - emitter = new IntegrationStreamWorkerEmitter(req.sqs, tracer, req.log) - await emitter.init() - } - - await emitter.triggerWebhookProcessing(integration.tenantId, integration.platform, result) + await req.emitters.integrationStreamWorker.triggerWebhookProcessing( + integration.tenantId, + integration.platform, + result, + ) res.sendStatus(204) } else { diff --git a/services/archetypes/worker/package.json b/services/archetypes/worker/package.json index 2642422e60..c0e12385fa 100644 --- a/services/archetypes/worker/package.json +++ b/services/archetypes/worker/package.json @@ -12,6 +12,9 @@ "@crowd/archetype-standard": "file:../../archetypes/standard", "@crowd/database": "file:../../libs/database", "@crowd/temporal": "file:../../libs/temporal", + "@crowd/common": "file:../../libs/common", + "@crowd/sqs": "file:../../libs/sqs", + "@opensearch-project/opensearch": "^1.2.0", "@temporalio/client": "~1.8.6", "@temporalio/worker": "~1.8.6", "@temporalio/workflow": "~1.8.6", diff --git a/services/archetypes/worker/src/index.ts b/services/archetypes/worker/src/index.ts index 4cd56b8cfa..a0805eeb89 100644 --- a/services/archetypes/worker/src/index.ts +++ b/services/archetypes/worker/src/index.ts @@ -4,7 +4,10 @@ import { NativeConnection, Worker as TemporalWorker, bundleWorkflowCode } from ' import { Config, Service } from '@crowd/archetype-standard' import { getDbConnection, DbStore } from '@crowd/database' +import { OpenSearchService } from '@crowd/opensearch' import { getDataConverter } from '@crowd/temporal' +import { IS_DEV_ENV, IS_TEST_ENV } from '@crowd/common' +import { SqsClient, getSqsClient } from '@crowd/sqs' // List all required environment variables, grouped per "component". // They are in addition to the ones required by the "standard" archetype. @@ -24,6 +27,25 @@ const envvars = { 'CROWD_DB_PASSWORD', 'CROWD_DB_DATABASE', ], + opensearch: + IS_DEV_ENV || IS_TEST_ENV + ? ['CROWD_OPENSEARCH_NODE'] + : [ + 'CROWD_OPENSEARCH_AWS_REGION', + 'CROWD_OPENSEARCH_AWS_ACCESS_KEY_ID', + 'CROWD_OPENSEARCH_AWS_SECRET_ACCESS_KEY', + 'CROWD_OPENSEARCH_NODE', + ], + sqs: + IS_DEV_ENV || IS_TEST_ENV + ? [ + 'CROWD_SQS_AWS_REGION', + 'CROWD_SQS_HOST', + 'CROWD_SQS_PORT', + 'CROWD_SQS_AWS_ACCESS_KEY_ID', + 'CROWD_SQS_AWS_SECRET_ACCESS_KEY', + ] + : ['CROWD_SQS_AWS_REGION', 'CROWD_SQS_AWS_ACCESS_KEY_ID', 'CROWD_SQS_AWS_SECRET_ACCESS_KEY'], } /* @@ -31,7 +53,14 @@ Options is used to configure the worker service. */ export interface Options { maxTaskQueueActivitiesPerSecond?: number - postgres: { + maxConcurrentActivityTaskExecutions?: number + postgres?: { + enabled: boolean + } + opensearch?: { + enabled: boolean + } + sqs?: { enabled: boolean } } @@ -43,9 +72,14 @@ export class ServiceWorker extends Service { readonly options: Options protected _worker: TemporalWorker + protected _postgresReader: DbStore protected _postgresWriter: DbStore + protected _opensearchService: OpenSearchService + + protected _sqsClient: SqsClient + constructor(config: Config, opts: Options) { super(config) @@ -53,7 +87,7 @@ export class ServiceWorker extends Service { } get postgres(): { reader: DbStore; writer: DbStore } | null { - if (!this.options.postgres.enabled) { + if (!this.options.postgres?.enabled) { return null } @@ -63,6 +97,22 @@ export class ServiceWorker extends Service { } } + get opensearch(): OpenSearchService { + if (!this.options.opensearch?.enabled) { + return null + } + + return this._opensearchService + } + + get sqs(): SqsClient { + if (!this.options.sqs?.enabled) { + return null + } + + return this._sqsClient + } + // We first need to ensure a standard service can be initialized given the config // and environment variables. override async init() { @@ -83,7 +133,7 @@ export class ServiceWorker extends Service { }) // Only validate PostgreSQL-related environment variables if enabled. - if (this.options.postgres.enabled) { + if (this.options.postgres?.enabled) { envvars.postgres.forEach((envvar) => { if (!process.env[envvar]) { missing.push(envvar) @@ -91,11 +141,86 @@ export class ServiceWorker extends Service { }) } + // Only validate OpenSearch-related environment variables if enabled. + if (this.options.opensearch?.enabled) { + envvars.opensearch.forEach((envvar) => { + if (!process.env[envvar]) { + missing.push(envvar) + } + }) + } + + // Only validate Sqs related environment variables if enabled + if (this.options.sqs?.enabled) { + envvars.sqs.forEach((envvar) => { + if (!process.env[envvar]) { + missing.push(envvar) + } + }) + } + // There's no point in continuing if a variable is missing. if (missing.length > 0) { throw new Error(`Missing environment variables: ${missing.join(', ')}`) } + if (this.options.postgres?.enabled) { + try { + const dbConnection = await getDbConnection({ + host: process.env['CROWD_DB_READ_HOST'], + port: Number(process.env['CROWD_DB_PORT']), + user: process.env['CROWD_DB_USERNAME'], + password: process.env['CROWD_DB_PASSWORD'], + database: process.env['CROWD_DB_DATABASE'], + }) + + this._postgresReader = new DbStore(this.log, dbConnection) + } catch (err) { + throw new Error(err) + } + + try { + const dbConnection = await getDbConnection({ + host: process.env['CROWD_DB_WRITE_HOST'], + port: Number(process.env['CROWD_DB_PORT']), + user: process.env['CROWD_DB_USERNAME'], + password: process.env['CROWD_DB_PASSWORD'], + database: process.env['CROWD_DB_DATABASE'], + }) + + this._postgresWriter = new DbStore(this.log, dbConnection) + } catch (err) { + throw new Error(err) + } + } + + if (this.options.opensearch?.enabled) { + try { + this._opensearchService = new OpenSearchService(this.log, { + region: process.env['CROWD_OPENSEARCH_AWS_REGION'], + accessKeyId: process.env['CROWD_OPENSEARCH_AWS_ACCESS_KEY_ID'], + secretAccessKey: process.env['CROWD_OPENSEARCH_AWS_SECRET_ACCESS_KEY'], + node: process.env['CROWD_OPENSEARCH_NODE'], + }) + } catch (err) { + throw new Error(err) + } + } + + if (this.options.sqs?.enabled) { + try { + this._sqsClient = getSqsClient({ + region: process.env['CROWD_SQS_AWS_REGION'], + host: process.env['CROWD_SQS_HOST'] ? process.env['CROWD_SQS_HOST'] : undefined, + port: process.env['CROWD_SQS_PORT'] ? Number(process.env['CROWD_SQS_PORT']) : undefined, + accessKeyId: process.env['CROWD_SQS_AWS_ACCESS_KEY_ID'], + secretAccessKey: process.env['CROWD_SQS_AWS_SECRET_ACCESS_KEY'], + }) + } catch (err) { + throw new Error(err) + } + } + try { const certificate = process.env['CROWD_TEMPORAL_CERTIFICATE'] const privateKey = process.env['CROWD_TEMPORAL_PRIVATE_KEY'] @@ -137,40 +262,11 @@ export class ServiceWorker extends Service { activities: require(path.resolve('./src/activities')), dataConverter: await getDataConverter(), maxTaskQueueActivitiesPerSecond: this.options.maxTaskQueueActivitiesPerSecond, + maxConcurrentActivityTaskExecutions: this.options.maxConcurrentActivityTaskExecutions, }) } catch (err) { throw new Error(err) } - - if (this.options.postgres.enabled) { - try { - const dbConnection = await getDbConnection({ - host: process.env['CROWD_DB_READ_HOST'], - port: Number(process.env['CROWD_DB_PORT']), - user: process.env['CROWD_DB_USERNAME'], - password: process.env['CROWD_DB_PASSWORD'], - database: process.env['CROWD_DB_DATABASE'], - }) - - this._postgresReader = new DbStore(this.log, dbConnection) - } catch (err) { - throw new Error(err) - } - - try { - const dbConnection = await getDbConnection({ - host: process.env['CROWD_DB_WRITE_HOST'], - port: Number(process.env['CROWD_DB_PORT']), - user: process.env['CROWD_DB_USERNAME'], - password: process.env['CROWD_DB_PASSWORD'], - database: process.env['CROWD_DB_DATABASE'], - }) - - this._postgresWriter = new DbStore(this.log, dbConnection) - } catch (err) { - throw new Error(err) - } - } } // Actually start the Temporal worker. @@ -185,7 +281,11 @@ export class ServiceWorker extends Service { // Stop allows to gracefully stop the service. Order for closing connections // matters. We need to stop the Temporal worker before closing other connections. protected override async stop() { - if (this.options.postgres.enabled) { + if (this.options.opensearch?.enabled) { + await this._opensearchService.client.close() + } + + if (this.options.postgres?.enabled) { this._postgresWriter.dbInstance.end() this._postgresReader.dbInstance.end() } diff --git a/services/libs/common/src/emailDomainValidator.ts b/services/libs/common/src/emailDomainValidator.ts index 2ec24f5090..45c1b0248f 100644 --- a/services/libs/common/src/emailDomainValidator.ts +++ b/services/libs/common/src/emailDomainValidator.ts @@ -1,4 +1,4 @@ -const excludeDomains = [ +const blacklistedDomains = [ 'gmail.com', 'yahoo.com', 'hotmail.com', @@ -104,8 +104,19 @@ const excludeDomains = [ 'pm.me', 'duck.com', 'zoho.com', + 'users.noreply.github.com', + '126.com', + '163.com', + 'foxmail.com', ] +/** + * Checks if a domain is part of the excluded domains. + * These domains are public email providers and not organizations. + * + * @param {string} domain - The domain name to check. + * @return {boolean} true if the domain is excluded, false otherwise. + */ export const isDomainExcluded = (domain: string) => { - return excludeDomains.includes(domain) + return blacklistedDomains.includes(domain) } diff --git a/services/libs/common/src/i18n/en.ts b/services/libs/common/src/i18n/en.ts index a21b511327..a32923dec0 100644 --- a/services/libs/common/src/i18n/en.ts +++ b/services/libs/common/src/i18n/en.ts @@ -93,6 +93,12 @@ const en = { }, }, + organization: { + errors: { + websiteAlreadyExists: 'Website already exists in another organization.', + }, + }, + errors: { notFound: { message: 'Page not found', diff --git a/services/libs/common/src/object.ts b/services/libs/common/src/object.ts index 07463c9101..23fd1a3202 100644 --- a/services/libs/common/src/object.ts +++ b/services/libs/common/src/object.ts @@ -34,3 +34,15 @@ export const mergeIgnoreUndefined = >(first: T return result } + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +type RemapT = { [index: string]: any } + +export const renameKeys = (obj: RemapT, fieldMap: RemapT): T => + Object.keys(obj).reduce( + (acc, key) => ({ + ...acc, + ...{ [fieldMap[key] || key]: obj[key] }, + }), + {} as T, + ) diff --git a/services/libs/common/src/requestThrottler.ts b/services/libs/common/src/requestThrottler.ts index 137acdeb4e..16dbd24169 100644 --- a/services/libs/common/src/requestThrottler.ts +++ b/services/libs/common/src/requestThrottler.ts @@ -53,8 +53,12 @@ export class RequestThrottler { this.refreshBackoff() return value } catch (error) { - this.logger.warn(`Error while executing throttling function!`) + this.logger.warn({ error }, `Error while executing throttling function!`) if (error) { + // we don't need to retry conflict errors, as they'll never succeed on retry + if (error.response?.data?.category === 'CONFLICT') { + throw error + } this.logger.info( `Starting exponential backoff with: ${this.backoff} seconds and factor: ${this.backoffFactor}!`, ) diff --git a/services/libs/common/src/timing.ts b/services/libs/common/src/timing.ts index 2c68d7696f..fb79ed0af6 100644 --- a/services/libs/common/src/timing.ts +++ b/services/libs/common/src/timing.ts @@ -10,3 +10,11 @@ export const addSeconds = (date: Date, seconds: number): Date => { } export const EPOCH_DATE = new Date('1970-01-01T00:00:00+00:00') + +export const getSecondsTillEndOfMonth = () => { + const now = new Date() + const endOfMonth = new Date(now.getFullYear(), now.getMonth() + 1, 0, 23, 59, 59) // Set to last day of current month, at 23:59:59 + + const diffInSeconds = (endOfMonth.getTime() - now.getTime()) / 1000 + return Math.round(diffInSeconds) +} diff --git a/services/libs/common/src/websiteNormalizer.ts b/services/libs/common/src/websiteNormalizer.ts index 94f57f4d31..8be2930873 100644 --- a/services/libs/common/src/websiteNormalizer.ts +++ b/services/libs/common/src/websiteNormalizer.ts @@ -1,12 +1,12 @@ import { parse, isValid } from 'psl' export const websiteNormalizer = (website: string): string => { - // remove http:// or https:// - const cleanURL = website.replace(/(^\w+:|^)\/\//, '') + // remove http:// or https:// and trailing slash + const cleanURL = website.replace(/^(?:https?:\/\/)?([^/]+)(?:\/.*)?$/, '$1') const parsed = parse(cleanURL) if (!isValid(cleanURL)) { - return null + throw new Error('Invalid website URL!') } return parsed.domain diff --git a/services/libs/common_services/.eslintrc.cjs b/services/libs/common_services/.eslintrc.cjs new file mode 100644 index 0000000000..4a8c9f2f7d --- /dev/null +++ b/services/libs/common_services/.eslintrc.cjs @@ -0,0 +1,21 @@ +module.exports = { + parser: '@typescript-eslint/parser', + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:prettier/recommended', + ], + plugins: ['@typescript-eslint', 'prettier'], + parserOptions: { + ecmaVersion: 2022, + sourceType: 'module', + }, + env: { + es6: true, + node: true, + }, + rules: { + 'prettier/prettier': 'error', + '@typescript-eslint/explicit-module-boundary-types': 'off', + }, +}; diff --git a/services/libs/common_services/.prettierignore b/services/libs/common_services/.prettierignore new file mode 100644 index 0000000000..323bc0d11c --- /dev/null +++ b/services/libs/common_services/.prettierignore @@ -0,0 +1,3 @@ +dist/ +.eslintrc.cjs +.prettierrc.cjs \ No newline at end of file diff --git a/services/libs/common_services/.prettierrc.cjs b/services/libs/common_services/.prettierrc.cjs new file mode 100644 index 0000000000..424d55813a --- /dev/null +++ b/services/libs/common_services/.prettierrc.cjs @@ -0,0 +1,7 @@ +module.exports = { + singleQuote: true, + arrowParens: 'always', + printWidth: 100, + trailingComma: 'all', + semi: false, +}; diff --git a/services/libs/common_services/package.json b/services/libs/common_services/package.json new file mode 100644 index 0000000000..dac2044604 --- /dev/null +++ b/services/libs/common_services/package.json @@ -0,0 +1,31 @@ +{ + "name": "@crowd/common_services", + "version": "1.0.0", + "private": true, + "scripts": { + "lint": "./node_modules/.bin/eslint --ext .ts src --max-warnings=0", + "format": "./node_modules/.bin/prettier --write \"src/**/*.ts\"", + "format-check": "./node_modules/.bin/prettier --check .", + "tsc-check": "./node_modules/.bin/tsc --noEmit" + }, + "devDependencies": { + "@types/node": "^18.16.3", + "@typescript-eslint/eslint-plugin": "^5.59.2", + "@typescript-eslint/parser": "^5.59.2", + "eslint": "^8.39.0", + "eslint-config-prettier": "^8.8.0", + "eslint-plugin-prettier": "^4.2.1", + "prettier": "^2.8.8", + "typescript": "^5.0.4" + }, + "dependencies": { + "@crowd/common": "file:../common", + "@crowd/logging": "file:../logging", + "@crowd/types": "file:../types", + "@crowd/database": "file:../database", + "@crowd/feature-flags": "file:../feature-flags", + "@crowd/redis": "file:../redis", + "@crowd/tracing": "file:../tracing", + "@crowd/sqs": "file:../sqs" + } +} diff --git a/services/libs/common_services/src/index.ts b/services/libs/common_services/src/index.ts new file mode 100644 index 0000000000..4c230b6055 --- /dev/null +++ b/services/libs/common_services/src/index.ts @@ -0,0 +1,2 @@ +export * from './services' +export * from './repos' diff --git a/services/libs/common_services/src/repos/index.ts b/services/libs/common_services/src/repos/index.ts new file mode 100644 index 0000000000..4c063ea2a7 --- /dev/null +++ b/services/libs/common_services/src/repos/index.ts @@ -0,0 +1 @@ +export * from './priorityLevelContext.repo' diff --git a/services/libs/common_services/src/repos/priorityLevelContext.repo.ts b/services/libs/common_services/src/repos/priorityLevelContext.repo.ts new file mode 100644 index 0000000000..71fd01b1d3 --- /dev/null +++ b/services/libs/common_services/src/repos/priorityLevelContext.repo.ts @@ -0,0 +1,26 @@ +import { DbStore, RepositoryBase } from '@crowd/database' +import { Logger } from '@crowd/logging' +import { IQueuePriorityCalculationContext } from '@crowd/types' + +export class PriorityLevelContextRepository extends RepositoryBase { + public constructor(dbStore: DbStore, parentLog: Logger) { + super(dbStore, parentLog) + } + + public async loadPriorityLevelContext( + tenantId: string, + ): Promise { + const result = await this.db().oneOrNone( + `select plan, "priorityLevel" as "dbPriority" from tenants where id = $(tenantId)`, + { + tenantId, + }, + ) + + if (result) { + return result + } + + throw new Error(`Tenant not found: ${tenantId}!`) + } +} diff --git a/services/libs/common_services/src/services/emitters/dataSinkWorker.emitter.ts b/services/libs/common_services/src/services/emitters/dataSinkWorker.emitter.ts new file mode 100644 index 0000000000..20e063192b --- /dev/null +++ b/services/libs/common_services/src/services/emitters/dataSinkWorker.emitter.ts @@ -0,0 +1,96 @@ +import { CrowdQueue, DATA_SINK_WORKER_QUEUE_SETTINGS, SqsClient } from '@crowd/sqs' +import { QueuePriorityContextLoader, QueuePriorityService } from '../priority.service' +import { RedisClient } from '@crowd/redis' +import { UnleashClient } from '@crowd/feature-flags' +import { Logger } from '@crowd/logging' +import { Tracer } from '@crowd/tracing' +import { + CheckResultsQueueMessage, + CreateAndProcessActivityResultQueueMessage, + IActivityData, + IQueueMessage, + ProcessIntegrationResultQueueMessage, + QueuePriorityLevel, +} from '@crowd/types' +import { generateUUIDv1 } from '@crowd/common' + +export class DataSinkWorkerEmitter extends QueuePriorityService { + public constructor( + sqsClient: SqsClient, + redis: RedisClient, + tracer: Tracer, + unleash: UnleashClient | undefined, + priorityLevelCalculationContextLoader: QueuePriorityContextLoader, + parentLog: Logger, + ) { + super( + CrowdQueue.DATA_SINK_WORKER, + DATA_SINK_WORKER_QUEUE_SETTINGS, + sqsClient, + redis, + tracer, + unleash, + priorityLevelCalculationContextLoader, + parentLog, + ) + } + + public async triggerResultProcessing( + tenantId: string, + platform: string, + resultId: string, + sourceId: string, + onboarding: boolean, + deduplicationId?: string, + ) { + await this.sendMessage( + tenantId, + sourceId, + new ProcessIntegrationResultQueueMessage(resultId), + deduplicationId || resultId, + { + onboarding, + }, + ) + } + + public async createAndProcessActivityResult( + tenantId: string, + segmentId: string, + integrationId: string, + activity: IActivityData, + ) { + await this.sendMessage( + tenantId, + generateUUIDv1(), + new CreateAndProcessActivityResultQueueMessage(tenantId, segmentId, integrationId, activity), + undefined, + { + onboarding: true, + }, + ) + } + + public async checkResults() { + await this.sendMessage( + undefined, + 'global', + new CheckResultsQueueMessage(), + 'global', + undefined, + QueuePriorityLevel.SYSTEM, + ) + } + + public sendMessagesBatch( + messages: { + tenantId: string + payload: T + groupId: string + deduplicationId?: string + id?: string + }[], + ): Promise { + return super.sendMessages(messages) + } +} diff --git a/services/libs/common_services/src/services/emitters/index.ts b/services/libs/common_services/src/services/emitters/index.ts new file mode 100644 index 0000000000..2a092a4b17 --- /dev/null +++ b/services/libs/common_services/src/services/emitters/index.ts @@ -0,0 +1,7 @@ +export * from './dataSinkWorker.emitter' +export * from './integrationDataWorker.emitter' +export * from './integrationRunWorker.emitter' +export * from './integrationStreamWorker.emitter' +export * from './integrationSyncWorker.emitter' +export * from './nodejsWorker.emitter' +export * from './searchSyncWorker.emitter' diff --git a/services/libs/common_services/src/services/emitters/integrationDataWorker.emitter.ts b/services/libs/common_services/src/services/emitters/integrationDataWorker.emitter.ts new file mode 100644 index 0000000000..4febba4e2d --- /dev/null +++ b/services/libs/common_services/src/services/emitters/integrationDataWorker.emitter.ts @@ -0,0 +1,40 @@ +import { CrowdQueue, INTEGRATION_DATA_WORKER_QUEUE_SETTINGS, SqsClient } from '@crowd/sqs' +import { QueuePriorityContextLoader, QueuePriorityService } from '../priority.service' +import { RedisClient } from '@crowd/redis' +import { Tracer } from '@crowd/tracing' +import { UnleashClient } from '@crowd/feature-flags' +import { Logger } from '@crowd/logging' +import { ProcessStreamDataQueueMessage } from '@crowd/types' + +export class IntegrationDataWorkerEmitter extends QueuePriorityService { + public constructor( + sqsClient: SqsClient, + redis: RedisClient, + tracer: Tracer, + unleash: UnleashClient | undefined, + priorityLevelCalculationContextLoader: QueuePriorityContextLoader, + parentLog: Logger, + ) { + super( + CrowdQueue.INTEGRATION_DATA_WORKER, + INTEGRATION_DATA_WORKER_QUEUE_SETTINGS, + sqsClient, + redis, + tracer, + unleash, + priorityLevelCalculationContextLoader, + parentLog, + ) + } + + public async triggerDataProcessing( + tenantId: string, + platform: string, + dataId: string, + onboarding: boolean, + ) { + await this.sendMessage(tenantId, dataId, new ProcessStreamDataQueueMessage(dataId), dataId, { + onboarding, + }) + } +} diff --git a/services/libs/common_services/src/services/emitters/integrationRunWorker.emitter.ts b/services/libs/common_services/src/services/emitters/integrationRunWorker.emitter.ts new file mode 100644 index 0000000000..37857bb502 --- /dev/null +++ b/services/libs/common_services/src/services/emitters/integrationRunWorker.emitter.ts @@ -0,0 +1,91 @@ +import { CrowdQueue, INTEGRATION_RUN_WORKER_QUEUE_SETTINGS, SqsClient } from '@crowd/sqs' +import { QueuePriorityContextLoader, QueuePriorityService } from '../priority.service' +import { RedisClient } from '@crowd/redis' +import { Tracer } from '@crowd/tracing' +import { UnleashClient } from '@crowd/feature-flags' +import { Logger } from '@crowd/logging' +import { + CheckRunsQueueMessage, + GenerateRunStreamsQueueMessage, + QueuePriorityLevel, + StartIntegrationRunQueueMessage, + StreamProcessedQueueMessage, +} from '@crowd/types' + +export class IntegrationRunWorkerEmitter extends QueuePriorityService { + public constructor( + sqsClient: SqsClient, + redis: RedisClient, + tracer: Tracer, + unleash: UnleashClient | undefined, + priorityLevelCalculationContextLoader: QueuePriorityContextLoader, + parentLog: Logger, + ) { + super( + CrowdQueue.INTEGRATION_RUN_WORKER, + INTEGRATION_RUN_WORKER_QUEUE_SETTINGS, + sqsClient, + redis, + tracer, + unleash, + priorityLevelCalculationContextLoader, + parentLog, + ) + } + + public async checkRuns() { + await this.sendMessage( + undefined, + 'global', + new CheckRunsQueueMessage(), + 'global', + undefined, + QueuePriorityLevel.SYSTEM, + ) + } + + public async triggerIntegrationRun( + tenantId: string, + platform: string, + integrationId: string, + onboarding: boolean, + isManualRun?: boolean, + manualSettings?: unknown, + ): Promise { + await this.sendMessage( + tenantId, + integrationId, + new StartIntegrationRunQueueMessage(integrationId, onboarding, isManualRun, manualSettings), + undefined, + { onboarding }, + ) + } + + public async triggerRunProcessing( + tenantId: string, + platform: string, + runId: string, + onboarding: boolean, + isManualRun?: boolean, + manualSettings?: unknown, + ): Promise { + await this.sendMessage( + tenantId, + runId, + new GenerateRunStreamsQueueMessage(runId, isManualRun, manualSettings), + runId, + { onboarding }, + ) + } + + public async streamProcessed( + tenantId: string, + platform: string, + runId: string, + onboarding: boolean, + ): Promise { + await this.sendMessage(tenantId, runId, new StreamProcessedQueueMessage(runId), undefined, { + onboarding, + }) + } +} diff --git a/services/libs/common_services/src/services/emitters/integrationStreamWorker.emitter.ts b/services/libs/common_services/src/services/emitters/integrationStreamWorker.emitter.ts new file mode 100644 index 0000000000..56036eefc3 --- /dev/null +++ b/services/libs/common_services/src/services/emitters/integrationStreamWorker.emitter.ts @@ -0,0 +1,91 @@ +import { UnleashClient } from '@crowd/feature-flags' +import { Logger } from '@crowd/logging' +import { RedisClient } from '@crowd/redis' +import { CrowdQueue, INTEGRATION_STREAM_WORKER_QUEUE_SETTINGS, SqsClient } from '@crowd/sqs' +import { Tracer } from '@crowd/tracing' +import { QueuePriorityContextLoader, QueuePriorityService } from '../priority.service' +import { + CheckStreamsQueueMessage, + ContinueProcessingRunStreamsQueueMessage, + ProcessStreamQueueMessage, + ProcessWebhookStreamQueueMessage, + QueuePriorityLevel, +} from '@crowd/types' +import { generateUUIDv1 } from '@crowd/common' + +export class IntegrationStreamWorkerEmitter extends QueuePriorityService { + public constructor( + sqsClient: SqsClient, + redis: RedisClient, + tracer: Tracer, + unleash: UnleashClient | undefined, + priorityLevelCalculationContextLoader: QueuePriorityContextLoader, + parentLog: Logger, + ) { + super( + CrowdQueue.INTEGRATION_STREAM_WORKER, + INTEGRATION_STREAM_WORKER_QUEUE_SETTINGS, + sqsClient, + redis, + tracer, + unleash, + priorityLevelCalculationContextLoader, + parentLog, + ) + } + + public async checkStreams() { + await this.sendMessage( + undefined, + 'global', + new CheckStreamsQueueMessage(), + 'global', + undefined, + QueuePriorityLevel.SYSTEM, + ) + } + + public async continueProcessingRunStreams( + tenantId: string, + onboarding: boolean, + platform: string, + runId: string, + ): Promise { + await this.sendMessage( + tenantId, + runId, + new ContinueProcessingRunStreamsQueueMessage(runId), + undefined, + { onboarding }, + ) + } + + public async triggerStreamProcessing( + tenantId: string, + platform: string, + streamId: string, + onboarding: boolean, + ): Promise { + await this.sendMessage( + tenantId, + generateUUIDv1(), + new ProcessStreamQueueMessage(streamId), + undefined, + { onboarding }, + ) + } + + public async triggerWebhookProcessing( + tenantId: string, + platform: string, + webhookId: string, + ): Promise { + await this.sendMessage( + tenantId, + generateUUIDv1(), + new ProcessWebhookStreamQueueMessage(webhookId), + undefined, + { onboarding: true }, + ) + } +} diff --git a/services/libs/sqs/src/instances/integrationSyncWorker.ts b/services/libs/common_services/src/services/emitters/integrationSyncWorker.emitter.ts similarity index 74% rename from services/libs/sqs/src/instances/integrationSyncWorker.ts rename to services/libs/common_services/src/services/emitters/integrationSyncWorker.emitter.ts index a0c038ead5..17c55a16b1 100644 --- a/services/libs/sqs/src/instances/integrationSyncWorker.ts +++ b/services/libs/common_services/src/services/emitters/integrationSyncWorker.emitter.ts @@ -1,11 +1,37 @@ +import { UnleashClient } from '@crowd/feature-flags' import { Logger } from '@crowd/logging' -import { AutomationSyncTrigger, IntegrationSyncWorkerQueueMessageType } from '@crowd/types' -import { INTEGRATION_SYNC_WORKER_QUEUE_SETTINGS, SqsClient, SqsQueueEmitter } from '..' +import { RedisClient } from '@crowd/redis' +import { CrowdQueue, INTEGRATION_SYNC_WORKER_QUEUE_SETTINGS, SqsClient } from '@crowd/sqs' import { Tracer } from '@crowd/tracing' +import { QueuePriorityContextLoader, QueuePriorityService } from '../priority.service' +import { + AutomationSyncTrigger, + IIntegrationSyncWorkerEmitter, + IntegrationSyncWorkerQueueMessageType, +} from '@crowd/types' -export class IntegrationSyncWorkerEmitter extends SqsQueueEmitter { - constructor(client: SqsClient, tracer: Tracer, parentLog: Logger) { - super(client, INTEGRATION_SYNC_WORKER_QUEUE_SETTINGS, tracer, parentLog) +export class IntegrationSyncWorkerEmitter + extends QueuePriorityService + implements IIntegrationSyncWorkerEmitter +{ + public constructor( + sqsClient: SqsClient, + redis: RedisClient, + tracer: Tracer, + unleash: UnleashClient | undefined, + priorityLevelCalculationContextLoader: QueuePriorityContextLoader, + parentLog: Logger, + ) { + super( + CrowdQueue.INTEGRATION_SYNC_WORKER, + INTEGRATION_SYNC_WORKER_QUEUE_SETTINGS, + sqsClient, + redis, + tracer, + unleash, + priorityLevelCalculationContextLoader, + parentLog, + ) } public async triggerSyncMarkedMembers(tenantId: string, integrationId: string): Promise { @@ -16,6 +42,7 @@ export class IntegrationSyncWorkerEmitter extends SqsQueueEmitter { throw new Error('integrationId is required!') } await this.sendMessage( + tenantId, integrationId, { type: IntegrationSyncWorkerQueueMessageType.SYNC_ALL_MARKED_MEMBERS, @@ -48,6 +75,7 @@ export class IntegrationSyncWorkerEmitter extends SqsQueueEmitter { } await this.sendMessage( + tenantId, memberId, { type: IntegrationSyncWorkerQueueMessageType.SYNC_MEMBER, @@ -76,6 +104,7 @@ export class IntegrationSyncWorkerEmitter extends SqsQueueEmitter { throw new Error('integrationId is required!') } await this.sendMessage( + tenantId, automationId, { type: IntegrationSyncWorkerQueueMessageType.ONBOARD_AUTOMATION, @@ -99,6 +128,7 @@ export class IntegrationSyncWorkerEmitter extends SqsQueueEmitter { throw new Error('integrationId is required!') } await this.sendMessage( + tenantId, integrationId, { type: IntegrationSyncWorkerQueueMessageType.SYNC_ALL_MARKED_ORGANIZATIONS, @@ -127,6 +157,7 @@ export class IntegrationSyncWorkerEmitter extends SqsQueueEmitter { } await this.sendMessage( + tenantId, organizationId, { type: IntegrationSyncWorkerQueueMessageType.SYNC_ORGANIZATION, diff --git a/services/libs/common_services/src/services/emitters/nodejsWorker.emitter.ts b/services/libs/common_services/src/services/emitters/nodejsWorker.emitter.ts new file mode 100644 index 0000000000..785fabbcf9 --- /dev/null +++ b/services/libs/common_services/src/services/emitters/nodejsWorker.emitter.ts @@ -0,0 +1,194 @@ +import { generateUUIDv1 } from '@crowd/common' +import { UnleashClient } from '@crowd/feature-flags' +import { Logger } from '@crowd/logging' +import { RedisClient } from '@crowd/redis' +import { CrowdQueue, NODEJS_WORKER_QUEUE_SETTINGS, SqsClient } from '@crowd/sqs' +import { Tracer } from '@crowd/tracing' +import { + AutomationType, + BulkEnrichQueueMessage, + EagleEyeEmailDigestQueueMessage, + EnrichOrganizationQueueMessage, + ExportCSVQueueMessage, + ExportableEntity, + IntegrationDataCheckerQueueMessage, + MergeSuggestionsQueueMessage, + NewActivityAutomationQueueMessage, + NewMemberAutomationQueueMessage, + ProcessAutomationQueueMessage, + QueuePriorityLevel, + RefreshSampleDataQueueMessage, + SendgridWebhookQueueMessage, + StripeWebhookQueueMessage, + WeeklyAnalyticsEmailQueueMessage, +} from '@crowd/types' +import { QueuePriorityContextLoader, QueuePriorityService } from '../priority.service' + +/* eslint-disable @typescript-eslint/no-explicit-any */ + +export class NodejsWorkerEmitter extends QueuePriorityService { + public constructor( + sqsClient: SqsClient, + redis: RedisClient, + tracer: Tracer, + unleash: UnleashClient | undefined, + priorityLevelCalculationContextLoader: QueuePriorityContextLoader, + parentLog: Logger, + ) { + super( + CrowdQueue.NODEJS_WORKER, + NODEJS_WORKER_QUEUE_SETTINGS, + sqsClient, + redis, + tracer, + unleash, + priorityLevelCalculationContextLoader, + parentLog, + ) + } + + public async processAutomationForNewActivity( + tenantId: string, + activityId: string, + segmentId: string, + onboarding: boolean, + ): Promise { + await this.sendMessage( + tenantId, + `${activityId}--${segmentId}`, + new NewActivityAutomationQueueMessage(tenantId, activityId, segmentId), + `${activityId}--${segmentId}`, + { + onboarding, + }, + ) + } + + public async processAutomationForNewMember( + tenantId: string, + memberId: string, + segmentId: string, + onboarding: boolean, + ): Promise { + await this.sendMessage( + tenantId, + memberId, + new NewMemberAutomationQueueMessage(tenantId, memberId, segmentId), + memberId, + { + onboarding, + }, + ) + } + + public async bulkEnrich( + tenantId: string, + memberIds: string[], + segmentIds: string[], + notifyFrontend = true, + skipCredits = false, + ): Promise { + await this.sendMessage( + tenantId, + generateUUIDv1(), + new BulkEnrichQueueMessage(tenantId, memberIds, segmentIds, notifyFrontend, skipCredits), + ) + } + + public async exportCSV( + tenantId: string, + user: string, + entity: ExportableEntity, + segmentIds: string[], + criteria: any, + ): Promise { + await this.sendMessage( + tenantId, + generateUUIDv1(), + new ExportCSVQueueMessage(user, tenantId, entity, segmentIds, criteria), + ) + } + + public async eagleEyeEmailDigest(tenantId: string, user: string): Promise { + await this.sendMessage( + tenantId, + generateUUIDv1(), + new EagleEyeEmailDigestQueueMessage(tenantId, user), + ) + } + + public async integrationDataChecker(tenantId: string, integrationId: string): Promise { + await this.sendMessage( + tenantId, + generateUUIDv1(), + new IntegrationDataCheckerQueueMessage(tenantId, integrationId), + ) + } + + public async processAutomation( + tenantId: string, + type: AutomationType, + automation: any, + eventId: string, + payload: any, + ): Promise { + await this.sendMessage( + tenantId, + generateUUIDv1(), + new ProcessAutomationQueueMessage(tenantId, type, automation, eventId, payload), + ) + } + + public async weeklyAnalyticsEmail(tenantId: string): Promise { + await this.sendMessage( + tenantId, + generateUUIDv1(), + new WeeklyAnalyticsEmailQueueMessage(tenantId), + ) + } + + public async stripeWebhook(event: any): Promise { + await this.sendMessage( + undefined, + generateUUIDv1(), + new StripeWebhookQueueMessage(event), + undefined, + undefined, + QueuePriorityLevel.SYSTEM, + ) + } + + public async sendgridWebhook(event: any): Promise { + await this.sendMessage( + undefined, + generateUUIDv1(), + new SendgridWebhookQueueMessage(event), + undefined, + undefined, + QueuePriorityLevel.SYSTEM, + ) + } + + public async refreshSampleData(): Promise { + await this.sendMessage( + undefined, + generateUUIDv1(), + new RefreshSampleDataQueueMessage(), + undefined, + undefined, + QueuePriorityLevel.SYSTEM, + ) + } + + public async enrichOrganizations(tenantId: string, maxEnrichLimit = 0): Promise { + await this.sendMessage( + tenantId, + tenantId, + new EnrichOrganizationQueueMessage(tenantId, maxEnrichLimit), + ) + } + + public async mergeSuggestions(tenantId: string): Promise { + await this.sendMessage(tenantId, tenantId, new MergeSuggestionsQueueMessage(tenantId)) + } +} diff --git a/services/libs/sqs/src/instances/searchSyncWorker.ts b/services/libs/common_services/src/services/emitters/searchSyncWorker.emitter.ts similarity index 54% rename from services/libs/sqs/src/instances/searchSyncWorker.ts rename to services/libs/common_services/src/services/emitters/searchSyncWorker.emitter.ts index 473b47ddb0..b8faeb3535 100644 --- a/services/libs/sqs/src/instances/searchSyncWorker.ts +++ b/services/libs/common_services/src/services/emitters/searchSyncWorker.emitter.ts @@ -1,14 +1,33 @@ +import { UnleashClient } from '@crowd/feature-flags' import { Logger } from '@crowd/logging' -import { SearchSyncWorkerQueueMessageType } from '@crowd/types' -import { SEARCH_SYNC_WORKER_QUEUE_SETTINGS, SqsClient, SqsQueueEmitter } from '..' +import { RedisClient } from '@crowd/redis' +import { CrowdQueue, SEARCH_SYNC_WORKER_QUEUE_SETTINGS, SqsClient } from '@crowd/sqs' import { Tracer } from '@crowd/tracing' +import { QueuePriorityContextLoader, QueuePriorityService } from '../priority.service' +import { SearchSyncWorkerQueueMessageType } from '@crowd/types' -export class SearchSyncWorkerEmitter extends SqsQueueEmitter { - constructor(client: SqsClient, tracer: Tracer, parentLog: Logger) { - super(client, SEARCH_SYNC_WORKER_QUEUE_SETTINGS, tracer, parentLog) +export class SearchSyncWorkerEmitter extends QueuePriorityService { + public constructor( + sqsClient: SqsClient, + redis: RedisClient, + tracer: Tracer, + unleash: UnleashClient | undefined, + priorityLevelCalculationContextLoader: QueuePriorityContextLoader, + parentLog: Logger, + ) { + super( + CrowdQueue.SEARCH_SYNC_WORKER, + SEARCH_SYNC_WORKER_QUEUE_SETTINGS, + sqsClient, + redis, + tracer, + unleash, + priorityLevelCalculationContextLoader, + parentLog, + ) } - public async triggerMemberSync(tenantId: string, memberId: string) { + public async triggerMemberSync(tenantId: string, memberId: string, onboarding: boolean) { if (!tenantId) { throw new Error('tenantId is required!') } @@ -17,12 +36,16 @@ export class SearchSyncWorkerEmitter extends SqsQueueEmitter { } await this.sendMessage( + tenantId, memberId, { type: SearchSyncWorkerQueueMessageType.SYNC_MEMBER, memberId, }, memberId, + { + onboarding, + }, ) } @@ -30,23 +53,39 @@ export class SearchSyncWorkerEmitter extends SqsQueueEmitter { if (!tenantId) { throw new Error('tenantId is required!') } - await this.sendMessage(tenantId, { + await this.sendMessage(tenantId, tenantId, { type: SearchSyncWorkerQueueMessageType.SYNC_TENANT_MEMBERS, tenantId, }) } - public async triggerOrganizationMembersSync(organizationId: string) { + public async triggerOrganizationMembersSync( + tenantId: string, + organizationId: string, + onboarding: boolean, + ) { + if (!tenantId) { + throw new Error('tenantId is required!') + } + if (!organizationId) { throw new Error('organizationId is required!') } - await this.sendMessage(organizationId, { - type: SearchSyncWorkerQueueMessageType.SYNC_ORGANIZATION_MEMBERS, + await this.sendMessage( + tenantId, organizationId, - }) + { + type: SearchSyncWorkerQueueMessageType.SYNC_ORGANIZATION_MEMBERS, + organizationId, + }, + undefined, + { + onboarding, + }, + ) } - public async triggerRemoveMember(tenantId: string, memberId: string) { + public async triggerRemoveMember(tenantId: string, memberId: string, onboarding: boolean) { if (!tenantId) { throw new Error('tenantId is required!') } @@ -54,23 +93,31 @@ export class SearchSyncWorkerEmitter extends SqsQueueEmitter { throw new Error('memberId is required!') } - await this.sendMessage(memberId, { - type: SearchSyncWorkerQueueMessageType.REMOVE_MEMBER, + await this.sendMessage( + tenantId, memberId, - }) + { + type: SearchSyncWorkerQueueMessageType.REMOVE_MEMBER, + memberId, + }, + undefined, + { + onboarding, + }, + ) } public async triggerMemberCleanup(tenantId: string) { if (!tenantId) { throw new Error('tenantId is required!') } - await this.sendMessage(tenantId, { + await this.sendMessage(tenantId, tenantId, { type: SearchSyncWorkerQueueMessageType.CLEANUP_TENANT_MEMBERS, tenantId, }) } - public async triggerActivitySync(tenantId: string, activityId: string) { + public async triggerActivitySync(tenantId: string, activityId: string, onboarding: boolean) { if (!tenantId) { throw new Error('tenantId is required!') } @@ -79,12 +126,16 @@ export class SearchSyncWorkerEmitter extends SqsQueueEmitter { } await this.sendMessage( + tenantId, activityId, { type: SearchSyncWorkerQueueMessageType.SYNC_ACTIVITY, activityId, }, activityId, + { + onboarding, + }, ) } @@ -92,23 +143,39 @@ export class SearchSyncWorkerEmitter extends SqsQueueEmitter { if (!tenantId) { throw new Error('tenantId is required!') } - await this.sendMessage(tenantId, { + await this.sendMessage(tenantId, tenantId, { type: SearchSyncWorkerQueueMessageType.SYNC_TENANT_ACTIVITIES, tenantId, }) } - public async triggerOrganizationActivitiesSync(organizationId: string) { + public async triggerOrganizationActivitiesSync( + tenantId: string, + organizationId: string, + onboarding: boolean, + ) { + if (!tenantId) { + throw new Error('tenantId is required!') + } + if (!organizationId) { throw new Error('organizationId is required!') } - await this.sendMessage(organizationId, { - type: SearchSyncWorkerQueueMessageType.SYNC_ORGANIZATION_ACTIVITIES, + await this.sendMessage( + tenantId, organizationId, - }) + { + type: SearchSyncWorkerQueueMessageType.SYNC_ORGANIZATION_ACTIVITIES, + organizationId, + }, + undefined, + { + onboarding, + }, + ) } - public async triggerRemoveActivity(tenantId: string, activityId: string) { + public async triggerRemoveActivity(tenantId: string, activityId: string, onboarding: boolean) { if (!tenantId) { throw new Error('tenantId is required!') } @@ -116,23 +183,35 @@ export class SearchSyncWorkerEmitter extends SqsQueueEmitter { throw new Error('activityId is required!') } - await this.sendMessage(activityId, { - type: SearchSyncWorkerQueueMessageType.REMOVE_ACTIVITY, + await this.sendMessage( + tenantId, activityId, - }) + { + type: SearchSyncWorkerQueueMessageType.REMOVE_ACTIVITY, + activityId, + }, + undefined, + { + onboarding, + }, + ) } public async triggerActivityCleanup(tenantId: string) { if (!tenantId) { throw new Error('tenantId is required!') } - await this.sendMessage(tenantId, { + await this.sendMessage(tenantId, tenantId, { type: SearchSyncWorkerQueueMessageType.CLEANUP_TENANT_ACTIVITIES, tenantId, }) } - public async triggerOrganizationSync(tenantId: string, organizationId: string) { + public async triggerOrganizationSync( + tenantId: string, + organizationId: string, + onboarding: boolean, + ) { if (!tenantId) { throw new Error('tenantId is required!') } @@ -141,12 +220,16 @@ export class SearchSyncWorkerEmitter extends SqsQueueEmitter { } await this.sendMessage( + tenantId, organizationId, { type: SearchSyncWorkerQueueMessageType.SYNC_ORGANIZATION, organizationId, }, - organizationId, + undefined, + { + onboarding, + }, ) } @@ -155,6 +238,7 @@ export class SearchSyncWorkerEmitter extends SqsQueueEmitter { throw new Error('tenantId is required!') } await this.sendMessage( + tenantId, tenantId, { type: SearchSyncWorkerQueueMessageType.SYNC_TENANT_ORGANIZATIONS, @@ -164,7 +248,11 @@ export class SearchSyncWorkerEmitter extends SqsQueueEmitter { ) } - public async triggerRemoveOrganization(tenantId: string, organizationId: string) { + public async triggerRemoveOrganization( + tenantId: string, + organizationId: string, + onboarding: boolean, + ) { if (!tenantId) { throw new Error('tenantId is required!') } @@ -172,10 +260,18 @@ export class SearchSyncWorkerEmitter extends SqsQueueEmitter { throw new Error('organizationId is required!') } - await this.sendMessage(organizationId, { - type: SearchSyncWorkerQueueMessageType.REMOVE_ORGANIZATION, + await this.sendMessage( + tenantId, organizationId, - }) + { + type: SearchSyncWorkerQueueMessageType.REMOVE_ORGANIZATION, + organizationId, + }, + undefined, + { + onboarding, + }, + ) } public async triggerOrganizationCleanup(tenantId: string) { @@ -183,6 +279,7 @@ export class SearchSyncWorkerEmitter extends SqsQueueEmitter { throw new Error('tenantId is required!') } await this.sendMessage( + tenantId, tenantId, { type: SearchSyncWorkerQueueMessageType.CLEANUP_TENANT_ORGANIZATIONS, diff --git a/services/libs/common_services/src/services/index.ts b/services/libs/common_services/src/services/index.ts new file mode 100644 index 0000000000..8967b647ab --- /dev/null +++ b/services/libs/common_services/src/services/index.ts @@ -0,0 +1,2 @@ +export * from './priority.service' +export * from './emitters' diff --git a/services/libs/common_services/src/services/priority.service.ts b/services/libs/common_services/src/services/priority.service.ts new file mode 100644 index 0000000000..4311a23d2e --- /dev/null +++ b/services/libs/common_services/src/services/priority.service.ts @@ -0,0 +1,223 @@ +import { EDITION, IS_DEV_ENV, IS_STAGING_ENV, IS_TEST_ENV, groupBy } from '@crowd/common' +import { UnleashClient, isFeatureEnabled } from '@crowd/feature-flags' +import { Logger, getChildLogger } from '@crowd/logging' +import { RedisCache, RedisClient } from '@crowd/redis' +import { CrowdQueue, ISqsQueueConfig, SqsClient, SqsPrioritizedQueueEmitter } from '@crowd/sqs' +import { Tracer } from '@crowd/tracing' +import { + FeatureFlag, + IQueuePriorityCalculationContext, + IQueueMessage, + QueuePriorityLevel, + TenantPlans, + Edition, +} from '@crowd/types' + +export type QueuePriorityContextLoader = ( + tenantId: string, +) => Promise + +export class QueuePriorityService { + private readonly log: Logger + private readonly cache: RedisCache + + private readonly emitter: SqsPrioritizedQueueEmitter + + public constructor( + public readonly queue: CrowdQueue, + private readonly queueConfig: ISqsQueueConfig, + private readonly sqsClient: SqsClient, + private readonly redis: RedisClient, + private readonly tracer: Tracer, + private readonly unleash: UnleashClient | undefined, + private readonly priorityLevelCalculationContextLoader: QueuePriorityContextLoader, + parentLog: Logger, + ) { + this.log = getChildLogger(this.constructor.name, parentLog) + this.cache = new RedisCache('queue-priority', redis, this.log) + this.emitter = new SqsPrioritizedQueueEmitter( + this.sqsClient, + this.queueConfig, + this.tracer, + this.log, + ) + } + + public isInitialized(): boolean { + return this.emitter.isInitialized() + } + + public async init(): Promise { + await this.emitter.init() + } + + public async setMessageVisibilityTimeout( + tenantId: string, + receiptHandle: string, + newVisibility: number, + ): Promise { + // feature flag will be cached for 5 minutes + if ( + isFeatureEnabled( + FeatureFlag.PRIORITIZED_QUEUES, + async () => { + return { + tenantId, + } + }, + this.unleash, + this.redis, + 5 * 60, + tenantId, + ) + ) { + const priorityLevel = await this.getPriorityLevel( + tenantId, + this.priorityLevelCalculationContextLoader, + ) + + return this.emitter.setMessageVisibilityTimeout(receiptHandle, newVisibility, priorityLevel) + } else { + return this.emitter.setMessageVisibilityTimeout(receiptHandle, newVisibility) + } + } + + public async sendMessages( + messages: { + tenantId: string + payload: T + groupId: string + deduplicationId?: string + id?: string + }[], + ): Promise { + const grouped = groupBy(messages, (m) => m.tenantId) + + for (const tenantId of Array.from(grouped.keys())) { + // feature flag will be cached for 5 minutes + if ( + isFeatureEnabled( + FeatureFlag.PRIORITIZED_QUEUES, + async () => { + return { + tenantId, + } + }, + this.unleash, + this.redis, + 5 * 60, + tenantId, + ) + ) { + const priorityLevel = await this.getPriorityLevel( + tenantId, + this.priorityLevelCalculationContextLoader, + ) + + return this.emitter.sendMessages( + messages.map((m) => { + return { ...m, priorityLevel } + }), + ) + } else { + return this.emitter.sendMessages(messages) + } + } + } + + public async sendMessage( + tenantId: string | undefined, + groupId: string, + message: T, + deduplicationId?: string, + priorityLevelContextOverride?: unknown, + priorityLevelOverride?: QueuePriorityLevel, + ): Promise { + // feature flag will be cached for 5 minutes + if ( + isFeatureEnabled( + FeatureFlag.PRIORITIZED_QUEUES, + async () => { + return { + tenantId, + } + }, + this.unleash, + this.redis, + 5 * 60, + tenantId, + ) + ) { + let priorityLevel = priorityLevelOverride + if (!priorityLevel) { + priorityLevel = await this.getPriorityLevel( + tenantId, + this.priorityLevelCalculationContextLoader, + priorityLevelContextOverride, + ) + } else if (IS_DEV_ENV || IS_TEST_ENV || IS_STAGING_ENV) { + priorityLevel = QueuePriorityLevel.NORMAL + } + + return this.emitter.sendMessage(groupId, message, deduplicationId, priorityLevel) + } else { + return this.emitter.sendMessage(groupId, message, deduplicationId) + } + } + + private async getPriorityLevel( + tenantId: string, + loader: QueuePriorityContextLoader, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + override?: any, + ): Promise { + if (IS_DEV_ENV || IS_TEST_ENV || IS_STAGING_ENV) { + return QueuePriorityLevel.NORMAL + } + + const cached = await this.cache.get(tenantId) + if (cached) { + return cached as QueuePriorityLevel + } + + let ctx = await loader(tenantId) + if (override) { + ctx = { ...ctx, ...override } + } + + const priority = this.calculateQueuePriorityLevel(ctx) + + // cache for 5 minutes + await this.cache.set(tenantId, priority, 5 * 60) + + return priority + } + + private calculateQueuePriorityLevel(ctx: IQueuePriorityCalculationContext): QueuePriorityLevel { + if (ctx.dbPriority) { + return ctx.dbPriority + } + + if (EDITION === Edition.LFX) { + if (ctx.onboarding) { + return QueuePriorityLevel.HIGH + } + + return QueuePriorityLevel.NORMAL + } + + if (ctx.plan === TenantPlans.Essential) { + if (ctx.onboarding) { + return QueuePriorityLevel.HIGH + } + + return QueuePriorityLevel.NORMAL + } else { + if (ctx.onboarding) { + return QueuePriorityLevel.URGENT + } + + return QueuePriorityLevel.HIGH + } + } +} diff --git a/services/libs/common_services/tsconfig.json b/services/libs/common_services/tsconfig.json new file mode 100644 index 0000000000..ed0f58b824 --- /dev/null +++ b/services/libs/common_services/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "target": "es2017", + "module": "commonjs", + "lib": ["es6", "es7", "es2017", "es2017.object", "es2015.promise"], + "skipLibCheck": true, + "sourceMap": true, + "moduleResolution": "node", + "experimentalDecorators": true, + "esModuleInterop": true, + "baseUrl": "./src", + "paths": { + "@crowd/*": ["../../*/src"] + } + }, + "include": ["src/**/*"] +} diff --git a/services/libs/cubejs/package.json b/services/libs/cubejs/package.json index 0c283f6e33..103a110713 100644 --- a/services/libs/cubejs/package.json +++ b/services/libs/cubejs/package.json @@ -11,7 +11,6 @@ "dependencies": { "@crowd/common": "file:../common", "@crowd/logging": "file:../logging", - "@cubejs-backend/server-core": "^0.32.27", "@cubejs-client/core": "~0.34.9", "jsonwebtoken": "~9.0.2", "moment": "~2.29.4" diff --git a/services/libs/cubejs/Dockerfile b/services/libs/cubejs/src/app/Dockerfile similarity index 57% rename from services/libs/cubejs/Dockerfile rename to services/libs/cubejs/src/app/Dockerfile index 264a3125cb..0a95e5aab5 100644 --- a/services/libs/cubejs/Dockerfile +++ b/services/libs/cubejs/src/app/Dockerfile @@ -1,3 +1,3 @@ FROM cubejs/cube:v0.33.55 -COPY ./ /cube/conf/ +COPY ./ /cube/conf/ \ No newline at end of file diff --git a/services/libs/cubejs/src/cube.ts b/services/libs/cubejs/src/app/cube.ts similarity index 94% rename from services/libs/cubejs/src/cube.ts rename to services/libs/cubejs/src/app/cube.ts index ac2bde634f..7198672b25 100644 --- a/services/libs/cubejs/src/cube.ts +++ b/services/libs/cubejs/src/app/cube.ts @@ -47,12 +47,6 @@ export default { query.timeDimensions[0].dateRange = ['2020-01-01', new Date().toISOString()] } - query.filters.push({ - member: `Members.isBot`, - operator: 'equals', - values: ['0'], - }) - query.filters.push({ member: `${measureCube[0]}.tenantId`, operator: 'equals', diff --git a/services/libs/cubejs/src/app/package-lock.json b/services/libs/cubejs/src/app/package-lock.json new file mode 100644 index 0000000000..729910a165 --- /dev/null +++ b/services/libs/cubejs/src/app/package-lock.json @@ -0,0 +1,10512 @@ +{ + "name": "weee", + "version": "1.0.1", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "weee", + "version": "1.0.1", + "dependencies": { + "@cubejs-backend/server-core": "^0.34.34" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "dependencies": { + "@babel/highlight": "^7.23.4", + "chalk": "^2.4.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", + "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.7.tgz", + "integrity": "sha512-+UpDgowcmqe36d4NwqvKsyPMlOLNGMsfMmQ5WGCu+siCe3t3dfe9njrzGfdN4qq+bcNUt0+Vw6haRxBOycs4dw==", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helpers": "^7.23.7", + "@babel/parser": "^7.23.6", + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.7", + "@babel/types": "^7.23.6", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", + "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", + "dependencies": { + "@babel/types": "^7.23.6", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", + "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz", + "integrity": "sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==", + "dependencies": { + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", + "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", + "dependencies": { + "@babel/compat-data": "^7.23.5", + "@babel/helper-validator-option": "^7.23.5", + "browserslist": "^4.22.2", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.23.7.tgz", + "integrity": "sha512-xCoqR/8+BoNnXOY7RVSgv6X+o7pmT5q1d+gGcRlXYkI+9B31glE4jeejhKVpA04O1AtzOt7OSQ6VYKP5FcRl9g==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-member-expression-to-functions": "^7.23.0", + "@babel/helper-optimise-call-expression": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.20", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz", + "integrity": "sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "regexpu-core": "^5.3.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.4.tgz", + "integrity": "sha512-QcJMILQCu2jm5TFPGA3lCpJJTeEP+mqeXooG/NZbg/h5FTFi6V0+99ahlRsW8/kRLyb24LZVCCiclDedhLKcBA==", + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz", + "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==", + "dependencies": { + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "dependencies": { + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz", + "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz", + "integrity": "sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-wrap-function": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz", + "integrity": "sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-member-expression-to-functions": "^7.22.15", + "@babel/helper-optimise-call-expression": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz", + "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", + "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz", + "integrity": "sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==", + "dependencies": { + "@babel/helper-function-name": "^7.22.5", + "@babel/template": "^7.22.15", + "@babel/types": "^7.22.19" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.7.tgz", + "integrity": "sha512-6AMnjCoC8wjqBzDHkuqpa7jAKwvMo4dC+lr/TFBz+ucfulO1XMpDnwWPGBNwClOKZ8h6xn5N81W/R5OrcKtCbQ==", + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.7", + "@babel/types": "^7.23.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.6.tgz", + "integrity": "sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==", + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.23.3.tgz", + "integrity": "sha512-iRkKcCqb7iGnq9+3G6rZ+Ciz5VywC4XNRHe57lKM+jOeYAoR0lVqdeeDRfh0tQcTfw/+vBhHn926FmQhLtlFLQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.23.3.tgz", + "integrity": "sha512-WwlxbfMNdVEpQjZmK5mhm7oSwD3dS6eU+Iwsi4Knl9wAletWem7kaRsGOG+8UEbRyqxY4SS5zvtfXwX+jMxUwQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-transform-optional-chaining": "^7.23.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.23.7.tgz", + "integrity": "sha512-LlRT7HgaifEpQA1ZgLVOIJZZFVPWN5iReq/7/JixwBtwcoeVGDBD53ZV28rrsLYOZs1Y/EHhA8N/Z6aazHR8cw==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.23.3.tgz", + "integrity": "sha512-lPgDSU+SJLK3xmFDTV2ZRQAiM7UuUjGidwBywFavObCiZc1BeAAcMtHJKUya92hPHO+at63JJPLygilZard8jw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.23.3.tgz", + "integrity": "sha512-pawnE0P9g10xgoP7yKr6CK63K2FMsTE+FZidZO/1PwRdzmAPVs+HS1mAURUsgaoxammTJvULUdIkEK0gOcU2tA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.23.3.tgz", + "integrity": "sha512-NzQcQrzaQPkaEwoTm4Mhyl8jI1huEL/WWIEvudjTCMJ9aBZNpsJbMASx7EQECtQQPS/DcnFpo0FIh3LvEO9cxQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.7.tgz", + "integrity": "sha512-PdxEpL71bJp1byMG0va5gwQcXHxuEYC/BgI/e88mGTtohbZN28O5Yit0Plkkm/dBzCF/BxmbNcses1RH1T+urA==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-remap-async-to-generator": "^7.22.20", + "@babel/plugin-syntax-async-generators": "^7.8.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.23.3.tgz", + "integrity": "sha512-A7LFsKi4U4fomjqXJlZg/u0ft/n8/7n7lpffUP/ZULx/DtV9SGlNKZolHH6PE8Xl1ngCc0M11OaeZptXVkfKSw==", + "dependencies": { + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-remap-async-to-generator": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.23.3.tgz", + "integrity": "sha512-vI+0sIaPIO6CNuM9Kk5VmXcMVRiOpDh7w2zZt9GXzmE/9KD70CUEVhvPR/etAeNK/FAEkhxQtXOzVF3EuRL41A==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.4.tgz", + "integrity": "sha512-0QqbP6B6HOh7/8iNR4CQU2Th/bbRtBp4KS9vcaZd1fZ0wSh5Fyssg0UCIHwxh+ka+pNDREbVLQnHCMHKZfPwfw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.23.3.tgz", + "integrity": "sha512-uM+AN8yCIjDPccsKGlw271xjJtGii+xQIF/uMPS8H15L12jZTsLfF4o5vNO7d/oUguOyfdikHGc/yi9ge4SGIg==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.23.4.tgz", + "integrity": "sha512-nsWu/1M+ggti1SOALj3hfx5FXzAY06fwPJsUZD4/A5e1bWi46VUIWtD+kOX6/IdhXGsXBWllLFDSnqSCdUNydQ==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.23.5.tgz", + "integrity": "sha512-jvOTR4nicqYC9yzOHIhXG5emiFEOpappSJAl73SDSEDcybD+Puuze8Tnpb9p9qEyYup24tq891gkaygIFvWDqg==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-optimise-call-expression": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.20", + "@babel/helper-split-export-declaration": "^7.22.6", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.23.3.tgz", + "integrity": "sha512-dTj83UVTLw/+nbiHqQSFdwO9CbTtwq1DsDqm3CUEtDrZNET5rT5E6bIdTlOftDTDLMYxvxHNEYO4B9SLl8SLZw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/template": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.3.tgz", + "integrity": "sha512-n225npDqjDIr967cMScVKHXJs7rout1q+tt50inyBCPkyZ8KxeI6d+GIbSBTT/w/9WdlWDOej3V9HE5Lgk57gw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.23.3.tgz", + "integrity": "sha512-vgnFYDHAKzFaTVp+mneDsIEbnJ2Np/9ng9iviHw3P/KVcgONxpNULEW/51Z/BaFojG2GI2GwwXck5uV1+1NOYQ==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.23.3.tgz", + "integrity": "sha512-RrqQ+BQmU3Oyav3J+7/myfvRCq7Tbz+kKLLshUmMwNlDHExbGL7ARhajvoBJEvc+fCguPPu887N+3RRXBVKZUA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.23.4.tgz", + "integrity": "sha512-V6jIbLhdJK86MaLh4Jpghi8ho5fGzt3imHOBu/x0jlBaPYqDoWz4RDXjmMOfnh+JWNaQleEAByZLV0QzBT4YQQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.23.3.tgz", + "integrity": "sha512-5fhCsl1odX96u7ILKHBj4/Y8vipoqwsJMh4csSA8qFfxrZDEA4Ssku2DyNvMJSmZNOEBT750LfFPbtrnTP90BQ==", + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.23.4.tgz", + "integrity": "sha512-GzuSBcKkx62dGzZI1WVgTWvkkz84FZO5TC5T8dl/Tht/rAla6Dg/Mz9Yhypg+ezVACf/rgDuQt3kbWEv7LdUDQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.23.6.tgz", + "integrity": "sha512-aYH4ytZ0qSuBbpfhuofbg/e96oQ7U2w1Aw/UQmKT+1l39uEhUPoFS3fHevDc1G0OvewyDudfMKY1OulczHzWIw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.23.3.tgz", + "integrity": "sha512-I1QXp1LxIvt8yLaib49dRW5Okt7Q4oaxao6tFVKS/anCdEOMtYwWVKoiOA1p34GOWIZjUK0E+zCp7+l1pfQyiw==", + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.23.4.tgz", + "integrity": "sha512-81nTOqM1dMwZ/aRXQ59zVubN9wHGqk6UtqRK+/q+ciXmRy8fSolhGVvG09HHRGo4l6fr/c4ZhXUQH0uFW7PZbg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-json-strings": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.23.3.tgz", + "integrity": "sha512-wZ0PIXRxnwZvl9AYpqNUxpZ5BiTGrYt7kueGQ+N5FiQ7RCOD4cm8iShd6S6ggfVIWaJf2EMk8eRzAh52RfP4rQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.23.4.tgz", + "integrity": "sha512-Mc/ALf1rmZTP4JKKEhUwiORU+vcfarFVLfcFiolKUo6sewoxSEgl36ak5t+4WamRsNr6nzjZXQjM35WsU+9vbg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.23.3.tgz", + "integrity": "sha512-sC3LdDBDi5x96LA+Ytekz2ZPk8i/Ck+DEuDbRAll5rknJ5XRTSaPKEYwomLcs1AA8wg9b3KjIQRsnApj+q51Ag==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.23.3.tgz", + "integrity": "sha512-vJYQGxeKM4t8hYCKVBlZX/gtIY2I7mRGFNcm85sgXGMTBcoV3QdVtdpbcWEbzbfUIUZKwvgFT82mRvaQIebZzw==", + "dependencies": { + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.3.tgz", + "integrity": "sha512-aVS0F65LKsdNOtcz6FRCpE4OgsP2OFnW46qNxNIX9h3wuzaNcSQsJysuMwqSibC98HPrf2vCgtxKNwS0DAlgcA==", + "dependencies": { + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-simple-access": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.3.tgz", + "integrity": "sha512-ZxyKGTkF9xT9YJuKQRo19ewf3pXpopuYQd8cDXqNzc3mUNbOME0RKMoZxviQk74hwzfQsEe66dE92MaZbdHKNQ==", + "dependencies": { + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.23.3.tgz", + "integrity": "sha512-zHsy9iXX2nIsCBFPud3jKn1IRPWg3Ing1qOZgeKV39m1ZgIdpJqvlWVeiHBZC6ITRG0MfskhYe9cLgntfSFPIg==", + "dependencies": { + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz", + "integrity": "sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.23.3.tgz", + "integrity": "sha512-YJ3xKqtJMAT5/TIZnpAR3I+K+WaDowYbN3xyxI8zxx/Gsypwf9B9h0VB+1Nh6ACAAPRS5NSRje0uVv5i79HYGQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.23.4.tgz", + "integrity": "sha512-jHE9EVVqHKAQx+VePv5LLGHjmHSJR76vawFPTdlxR/LVJPfOEGxREQwQfjuZEOPTwG92X3LINSh3M40Rv4zpVA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.23.4.tgz", + "integrity": "sha512-mps6auzgwjRrwKEZA05cOwuDc9FAzoyFS4ZsG/8F43bTLf/TgkJg7QXOrPO1JO599iA3qgK9MXdMGOEC8O1h6Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.23.4.tgz", + "integrity": "sha512-9x9K1YyeQVw0iOXJlIzwm8ltobIIv7j2iLyP2jIhEbqPRQ7ScNgwQufU2I0Gq11VjyG4gI4yMXt2VFags+1N3g==", + "dependencies": { + "@babel/compat-data": "^7.23.3", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.23.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.23.3.tgz", + "integrity": "sha512-BwQ8q0x2JG+3lxCVFohg+KbQM7plfpBwThdW9A6TMtWwLsbDA01Ek2Zb/AgDN39BiZsExm4qrXxjk+P1/fzGrA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.23.4.tgz", + "integrity": "sha512-XIq8t0rJPHf6Wvmbn9nFxU6ao4c7WhghTR5WyV8SrJfUFzyxhCm4nhC+iAp3HFhbAKLfYpgzhJ6t4XCtVwqO5A==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.4.tgz", + "integrity": "sha512-ZU8y5zWOfjM5vZ+asjgAPwDaBjJzgufjES89Rs4Lpq63O300R/kOz30WCLo6BxxX6QVEilwSlpClnG5cZaikTA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.23.3.tgz", + "integrity": "sha512-09lMt6UsUb3/34BbECKVbVwrT9bO6lILWln237z7sLaWnMsTi7Yc9fhX5DLpkJzAGfaReXI22wP41SZmnAA3Vw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.23.3.tgz", + "integrity": "sha512-UzqRcRtWsDMTLrRWFvUBDwmw06tCQH9Rl1uAjfh6ijMSmGYQ+fpdB+cnqRC8EMh5tuuxSv0/TejGL+7vyj+50g==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.23.4.tgz", + "integrity": "sha512-9G3K1YqTq3F4Vt88Djx1UZ79PDyj+yKRnUy7cZGSMe+a7jkwD259uKKuUzQlPkGam7R+8RJwh5z4xO27fA1o2A==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.23.3.tgz", + "integrity": "sha512-jR3Jn3y7cZp4oEWPFAlRsSWjxKe4PZILGBSd4nis1TsC5qeSpb+nrtihJuDhNI7QHiVbUaiXa0X2RZY3/TI6Nw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.23.3.tgz", + "integrity": "sha512-KP+75h0KghBMcVpuKisx3XTu9Ncut8Q8TuvGO4IhY+9D5DFEckQefOuIsB/gQ2tG71lCke4NMrtIPS8pOj18BQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "regenerator-transform": "^0.15.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.23.3.tgz", + "integrity": "sha512-QnNTazY54YqgGxwIexMZva9gqbPa15t/x9VS+0fsEFWplwVpXYZivtgl43Z1vMpc1bdPP2PP8siFeVcnFvA3Cg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.23.3.tgz", + "integrity": "sha512-ED2fgqZLmexWiN+YNFX26fx4gh5qHDhn1O2gvEhreLW2iI63Sqm4llRLCXALKrCnbN4Jy0VcMQZl/SAzqug/jg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.23.3.tgz", + "integrity": "sha512-VvfVYlrlBVu+77xVTOAoxQ6mZbnIq5FM0aGBSFEcIh03qHf+zNqA4DC/3XMUozTg7bZV3e3mZQ0i13VB6v5yUg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.23.3.tgz", + "integrity": "sha512-HZOyN9g+rtvnOU3Yh7kSxXrKbzgrm5X4GncPY1QOquu7epga5MxKHVpYu2hvQnry/H+JjckSYRb93iNfsioAGg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.23.3.tgz", + "integrity": "sha512-Flok06AYNp7GV2oJPZZcP9vZdszev6vPBkHLwxwSpaIqx75wn6mUd3UFWsSsA0l8nXAKkyCmL/sR02m8RYGeHg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.23.3.tgz", + "integrity": "sha512-4t15ViVnaFdrPC74be1gXBSMzXk3B4Us9lP7uLRQHTFpV5Dvt33pn+2MyyNxmN3VTTm3oTrZVMUmuw3oBnQ2oQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.23.3.tgz", + "integrity": "sha512-OMCUx/bU6ChE3r4+ZdylEqAjaQgHAgipgW8nsCfu5pGqDcFytVd91AwRvUJSBZDz0exPGgnjoqhgRYLRjFZc9Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.23.3.tgz", + "integrity": "sha512-KcLIm+pDZkWZQAFJ9pdfmh89EwVfmNovFBcXko8szpBeF8z68kWIPeKlmSOkT9BXJxs2C0uk+5LxoxIv62MROA==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.23.3.tgz", + "integrity": "sha512-wMHpNA4x2cIA32b/ci3AfwNgheiva2W0WUKWTK7vBHBhDKfPsc5cFGNWm69WBqpwd86u1qwZ9PWevKqm1A3yAw==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.23.3.tgz", + "integrity": "sha512-W7lliA/v9bNR83Qc3q1ip9CQMZ09CcHDbHfbLRDNuAhn1Mvkr1ZNF7hPmztMQvtTGVLJ9m8IZqWsTkXOml8dbw==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.23.7.tgz", + "integrity": "sha512-SY27X/GtTz/L4UryMNJ6p4fH4nsgWbz84y9FE0bQeWJP6O5BhgVCt53CotQKHCOeXJel8VyhlhujhlltKms/CA==", + "dependencies": { + "@babel/compat-data": "^7.23.5", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-option": "^7.23.5", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.23.3", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.23.3", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.23.7", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.23.3", + "@babel/plugin-syntax-import-attributes": "^7.23.3", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.23.3", + "@babel/plugin-transform-async-generator-functions": "^7.23.7", + "@babel/plugin-transform-async-to-generator": "^7.23.3", + "@babel/plugin-transform-block-scoped-functions": "^7.23.3", + "@babel/plugin-transform-block-scoping": "^7.23.4", + "@babel/plugin-transform-class-properties": "^7.23.3", + "@babel/plugin-transform-class-static-block": "^7.23.4", + "@babel/plugin-transform-classes": "^7.23.5", + "@babel/plugin-transform-computed-properties": "^7.23.3", + "@babel/plugin-transform-destructuring": "^7.23.3", + "@babel/plugin-transform-dotall-regex": "^7.23.3", + "@babel/plugin-transform-duplicate-keys": "^7.23.3", + "@babel/plugin-transform-dynamic-import": "^7.23.4", + "@babel/plugin-transform-exponentiation-operator": "^7.23.3", + "@babel/plugin-transform-export-namespace-from": "^7.23.4", + "@babel/plugin-transform-for-of": "^7.23.6", + "@babel/plugin-transform-function-name": "^7.23.3", + "@babel/plugin-transform-json-strings": "^7.23.4", + "@babel/plugin-transform-literals": "^7.23.3", + "@babel/plugin-transform-logical-assignment-operators": "^7.23.4", + "@babel/plugin-transform-member-expression-literals": "^7.23.3", + "@babel/plugin-transform-modules-amd": "^7.23.3", + "@babel/plugin-transform-modules-commonjs": "^7.23.3", + "@babel/plugin-transform-modules-systemjs": "^7.23.3", + "@babel/plugin-transform-modules-umd": "^7.23.3", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5", + "@babel/plugin-transform-new-target": "^7.23.3", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.23.4", + "@babel/plugin-transform-numeric-separator": "^7.23.4", + "@babel/plugin-transform-object-rest-spread": "^7.23.4", + "@babel/plugin-transform-object-super": "^7.23.3", + "@babel/plugin-transform-optional-catch-binding": "^7.23.4", + "@babel/plugin-transform-optional-chaining": "^7.23.4", + "@babel/plugin-transform-parameters": "^7.23.3", + "@babel/plugin-transform-private-methods": "^7.23.3", + "@babel/plugin-transform-private-property-in-object": "^7.23.4", + "@babel/plugin-transform-property-literals": "^7.23.3", + "@babel/plugin-transform-regenerator": "^7.23.3", + "@babel/plugin-transform-reserved-words": "^7.23.3", + "@babel/plugin-transform-shorthand-properties": "^7.23.3", + "@babel/plugin-transform-spread": "^7.23.3", + "@babel/plugin-transform-sticky-regex": "^7.23.3", + "@babel/plugin-transform-template-literals": "^7.23.3", + "@babel/plugin-transform-typeof-symbol": "^7.23.3", + "@babel/plugin-transform-unicode-escapes": "^7.23.3", + "@babel/plugin-transform-unicode-property-regex": "^7.23.3", + "@babel/plugin-transform-unicode-regex": "^7.23.3", + "@babel/plugin-transform-unicode-sets-regex": "^7.23.3", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.7", + "babel-plugin-polyfill-corejs3": "^0.8.7", + "babel-plugin-polyfill-regenerator": "^0.5.4", + "core-js-compat": "^3.31.0", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==" + }, + "node_modules/@babel/runtime": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.7.tgz", + "integrity": "sha512-w06OXVOFso7LcbzMiDGt+3X7Rh7Ho8MmgPoWU3rarH+8upf+wSU/grlGbWzQyr3DkdN6ZeuMFjpdwW0Q+HxobA==", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/standalone": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/standalone/-/standalone-7.23.7.tgz", + "integrity": "sha512-AsO3aIh9I4qIqK61d6nPxPAdrSuWF4FmOLej3xNIkBIZj+8XJGArQQJw6DnuUkkqbsLp1fARkXOdKiuqWgac0Q==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.7.tgz", + "integrity": "sha512-tY3mM8rH9jM0YHFGyfC0/xf+SB5eKUu7HPj7/k3fpi9dAlsMc5YbQvDi0Sh2QTPXqMhyaAtzAr807TIyfQrmyg==", + "dependencies": { + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.6", + "@babel/types": "^7.23.6", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.6.tgz", + "integrity": "sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==", + "dependencies": { + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@cubejs-backend/api-gateway": { + "version": "0.34.42", + "resolved": "https://registry.npmjs.org/@cubejs-backend/api-gateway/-/api-gateway-0.34.42.tgz", + "integrity": "sha512-jj1TfsqXYQZXYdQ6yjjqfMxlC+B8C7zALunZWNy8Sy49kcZN1idA3nldOxYBLqEgZDGi0a6py+KyxCvPbI1yRQ==", + "dependencies": { + "@cubejs-backend/native": "^0.34.42", + "@cubejs-backend/shared": "^0.34.41", + "@ungap/structured-clone": "^0.3.4", + "body-parser": "^1.19.0", + "chrono-node": "^2.6.2", + "express-graphql": "^0.12.0", + "graphql": "^15.8.0", + "graphql-scalars": "^1.10.0", + "inflection": "^1.12.0", + "joi": "^17.8.3", + "jsonwebtoken": "^8.3.0", + "jwk-to-pem": "^2.0.4", + "moment": "^2.24.0", + "moment-timezone": "^0.5.27", + "nexus": "^1.1.0", + "node-fetch": "^2.6.1", + "ramda": "^0.27.0", + "uuid": "^8.3.2" + }, + "engines": { + "node": "^14.0.0 || ^16.0.0 || >=17.0.0" + } + }, + "node_modules/@cubejs-backend/api-gateway/node_modules/jsonwebtoken": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", + "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=4", + "npm": ">=1.4.28" + } + }, + "node_modules/@cubejs-backend/api-gateway/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/@cubejs-backend/base-driver": { + "version": "0.34.41", + "resolved": "https://registry.npmjs.org/@cubejs-backend/base-driver/-/base-driver-0.34.41.tgz", + "integrity": "sha512-ndAgqk92VyOgfcFoOFF3feI2qcjW2txKganmrUbjC/bnXcg4E5y8BruC8dhCD2qMJdbFOOrCFBaNVw8ZIlaHVA==", + "dependencies": { + "@cubejs-backend/shared": "^0.34.41", + "ramda": "^0.27.0" + }, + "engines": { + "node": "^14.0.0 || ^16.0.0 || >=17.0.0" + } + }, + "node_modules/@cubejs-backend/cloud": { + "version": "0.34.41", + "resolved": "https://registry.npmjs.org/@cubejs-backend/cloud/-/cloud-0.34.41.tgz", + "integrity": "sha512-rmWcP2nWLogyl2m2ny0uxqXUPeoH4oI1JHov6snEWenuRFac6SLJ+ElF7SL2MAp/AEbtsvGgrE2CIFLWSqYOAQ==", + "dependencies": { + "@cubejs-backend/dotenv": "^9.0.2", + "@cubejs-backend/shared": "^0.34.41", + "chokidar": "^3.5.1", + "env-var": "^6.3.0", + "fs-extra": "^9.1.0", + "jsonwebtoken": "^8.5.1", + "request": "^2.88.2", + "request-promise": "^4.2.5" + }, + "engines": { + "node": "^14.0.0 || ^16.0.0 || >=17.0.0" + } + }, + "node_modules/@cubejs-backend/cloud/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@cubejs-backend/cloud/node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@cubejs-backend/cloud/node_modules/jsonwebtoken": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", + "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=4", + "npm": ">=1.4.28" + } + }, + "node_modules/@cubejs-backend/cloud/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/@cubejs-backend/cloud/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@cubejs-backend/cubesql": { + "version": "0.34.42", + "resolved": "https://registry.npmjs.org/@cubejs-backend/cubesql/-/cubesql-0.34.42.tgz", + "integrity": "sha512-6HUwteg1Dwsju/qxBIpbdYbuJyfI2jVWI3wCdsvS0PKB9b9XM8r4oQkqcaeBZFmcw2yJjgEhNWrXjBvTH2mu3A==", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@cubejs-backend/cubestore": { + "version": "0.34.41", + "resolved": "https://registry.npmjs.org/@cubejs-backend/cubestore/-/cubestore-0.34.41.tgz", + "integrity": "sha512-lseD9o3KogTcyPk5Rqv8wjoC3Yyf24/V3fOBM+wn3QR3cC+uLHIPuaszWdlgki/SAk1ZqNWCKECGypY3snBEQw==", + "hasInstallScript": true, + "dependencies": { + "@cubejs-backend/shared": "^0.34.41", + "@octokit/core": "^3.2.5", + "source-map-support": "^0.5.19" + }, + "bin": { + "cubestore-dev": "bin/cubestore-dev" + }, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@cubejs-backend/cubestore-driver": { + "version": "0.34.41", + "resolved": "https://registry.npmjs.org/@cubejs-backend/cubestore-driver/-/cubestore-driver-0.34.41.tgz", + "integrity": "sha512-UrMkqpwOEHJC+s99MVvkUKwzd/lX+5qTi05giYZRcwnFL18eU5epcGbYwwTbmFbZLlYs5ESJ+BfLL4fjNsp40Q==", + "dependencies": { + "@cubejs-backend/base-driver": "^0.34.41", + "@cubejs-backend/cubestore": "^0.34.41", + "@cubejs-backend/shared": "^0.34.41", + "csv-write-stream": "^2.0.0", + "flatbuffers": "23.3.3", + "fs-extra": "^9.1.0", + "generic-pool": "^3.6.0", + "moment-timezone": "^0.5.31", + "node-fetch": "^2.6.1", + "sqlstring": "^2.3.3", + "tempy": "^1.0.1", + "uuid": "^8.3.2", + "ws": "^7.4.3" + }, + "engines": { + "node": "^14.0.0 || ^16.0.0 || >=17.0.0" + } + }, + "node_modules/@cubejs-backend/cubestore-driver/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@cubejs-backend/cubestore-driver/node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@cubejs-backend/cubestore-driver/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@cubejs-backend/dotenv": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/@cubejs-backend/dotenv/-/dotenv-9.0.2.tgz", + "integrity": "sha512-yC1juhXEjM7K97KfXubDm7WGipd4Lpxe+AT8XeTRE9meRULrKlw0wtE2E8AQkGOfTBn+P1SCkePQ/BzIbOh1VA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@cubejs-backend/native": { + "version": "0.34.42", + "resolved": "https://registry.npmjs.org/@cubejs-backend/native/-/native-0.34.42.tgz", + "integrity": "sha512-HKU+I57wUfZVsVijURrj/jMErFAq231MymKsqvRC/WMogOR32VXRA8JNlUp04KPJoYPG68AZLoKn0TL3aQREkA==", + "hasInstallScript": true, + "dependencies": { + "@cubejs-backend/cubesql": "^0.34.42", + "@cubejs-backend/shared": "^0.34.41", + "@cubejs-infra/post-installer": "^0.0.7" + }, + "engines": { + "node": "^14.0.0 || ^16.0.0 || >=17.0.0" + } + }, + "node_modules/@cubejs-backend/query-orchestrator": { + "version": "0.34.41", + "resolved": "https://registry.npmjs.org/@cubejs-backend/query-orchestrator/-/query-orchestrator-0.34.41.tgz", + "integrity": "sha512-3LtXiIenuXtqGGiFILMkEl2ZqVbpPW6cc2y9O7toFFgzbxSwR+6diJrFMthvaLAAkloeMqe9sW4FWypi7CI39g==", + "dependencies": { + "@cubejs-backend/base-driver": "^0.34.41", + "@cubejs-backend/cubestore-driver": "^0.34.41", + "@cubejs-backend/shared": "^0.34.41", + "csv-write-stream": "^2.0.0", + "es5-ext": "0.10.53", + "generic-pool": "^3.7.1", + "ioredis": "^4.27.8", + "lru-cache": "^6.0.0", + "moment-range": "^4.0.2", + "moment-timezone": "^0.5.33", + "ramda": "^0.27.2", + "redis": "^3.0.2" + }, + "engines": { + "node": "^14.0.0 || ^16.0.0 || >=17.0.0" + } + }, + "node_modules/@cubejs-backend/query-orchestrator/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@cubejs-backend/query-orchestrator/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/@cubejs-backend/schema-compiler": { + "version": "0.34.42", + "resolved": "https://registry.npmjs.org/@cubejs-backend/schema-compiler/-/schema-compiler-0.34.42.tgz", + "integrity": "sha512-+3sHT7+ZaMjBcfTPy9My0YEl4GFtVwWwfJaal9vpsdIyMcxFA5RHwDAr3nryFh0CR9JK6r4uX24JwZIvuZPzXQ==", + "dependencies": { + "@babel/code-frame": "^7.12.11", + "@babel/core": "^7.12.10", + "@babel/generator": "^7.12.10", + "@babel/parser": "^7.12.10", + "@babel/preset-env": "^7.12.10", + "@babel/standalone": "^7.12.10", + "@babel/traverse": "^7.12.10", + "@babel/types": "^7.12.12", + "@cubejs-backend/native": "^0.34.42", + "@cubejs-backend/shared": "^0.34.41", + "antlr4ts": "0.5.0-alpha.4", + "camelcase": "^6.2.0", + "cron-parser": "^3.5.0", + "humps": "^2.0.1", + "inflection": "^1.12.0", + "joi": "^17.8.3", + "js-yaml": "^4.1.0", + "lru-cache": "^5.1.1", + "moment-range": "^4.0.1", + "moment-timezone": "^0.5.33", + "node-dijkstra": "^2.5.0", + "ramda": "^0.27.2", + "syntax-error": "^1.3.0", + "uuid": "^8.3.2" + }, + "engines": { + "node": "^14.0.0 || ^16.0.0 || >=17.0.0" + } + }, + "node_modules/@cubejs-backend/server-core": { + "version": "0.34.42", + "resolved": "https://registry.npmjs.org/@cubejs-backend/server-core/-/server-core-0.34.42.tgz", + "integrity": "sha512-+OEKjBVzJx0JGCqxLwXSTG5RKzE6ngyQj1L029BAnkxxb/V1pl4NoOCa3vimDC8zfpLMIxeIipvt+j2L8ml3HA==", + "dependencies": { + "@cubejs-backend/api-gateway": "^0.34.42", + "@cubejs-backend/cloud": "^0.34.41", + "@cubejs-backend/dotenv": "^9.0.2", + "@cubejs-backend/native": "^0.34.42", + "@cubejs-backend/query-orchestrator": "^0.34.41", + "@cubejs-backend/schema-compiler": "^0.34.42", + "@cubejs-backend/shared": "^0.34.41", + "@cubejs-backend/templates": "^0.34.41", + "codesandbox-import-utils": "^2.1.12", + "cross-spawn": "^7.0.1", + "fs-extra": "^8.1.0", + "is-docker": "^2.1.1", + "joi": "^17.8.3", + "jsonwebtoken": "^8.4.0", + "lodash.clonedeep": "^4.5.0", + "lru-cache": "^5.1.1", + "moment": "^2.29.1", + "node-fetch": "^2.6.0", + "p-limit": "^3.1.0", + "promise-timeout": "^1.3.0", + "ramda": "^0.27.0", + "semver": "^6.3.0", + "serve-static": "^1.13.2", + "sqlstring": "^2.3.1", + "uuid": "^8.3.2", + "ws": "^7.5.3" + }, + "engines": { + "node": "^14.0.0 || ^16.0.0 || >=17.0.0" + } + }, + "node_modules/@cubejs-backend/server-core/node_modules/jsonwebtoken": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", + "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=4", + "npm": ">=1.4.28" + } + }, + "node_modules/@cubejs-backend/server-core/node_modules/jsonwebtoken/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/@cubejs-backend/shared": { + "version": "0.34.41", + "resolved": "https://registry.npmjs.org/@cubejs-backend/shared/-/shared-0.34.41.tgz", + "integrity": "sha512-WcXPhkCj+STThblbz/J4K6/lefa+L39OrD7CBwSV7CO5Fb9SsFbry7F5gyget2sopkdbwpwJd6zXHFu/03RwOg==", + "dependencies": { + "@oclif/color": "^0.1.2", + "bytes": "^3.1.0", + "cli-progress": "^3.9.0", + "cross-spawn": "^7.0.3", + "decompress": "^4.2.1", + "env-var": "^6.3.0", + "fs-extra": "^9.1.0", + "http-proxy-agent": "^4.0.1", + "moment-range": "^4.0.1", + "moment-timezone": "^0.5.33", + "node-fetch": "^2.6.1", + "shelljs": "^0.8.5", + "throttle-debounce": "^3.0.1", + "uuid": "^8.3.2" + }, + "engines": { + "node": "^14.0.0 || ^16.0.0 || >=17.0.0" + } + }, + "node_modules/@cubejs-backend/shared/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@cubejs-backend/shared/node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@cubejs-backend/shared/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@cubejs-backend/templates": { + "version": "0.34.41", + "resolved": "https://registry.npmjs.org/@cubejs-backend/templates/-/templates-0.34.41.tgz", + "integrity": "sha512-NcbksDuYIG9NbBHzKZNnrmh3Ih+VXTr2SLKMmiqRMcKmFU36Z2LXNGaZl0CAexnuHJfVJq39WVZQ+maxFIPY6A==", + "dependencies": { + "@cubejs-backend/shared": "^0.34.41", + "cross-spawn": "^7.0.3", + "decompress": "^4.2.1", + "decompress-targz": "^4.1.1", + "fs-extra": "^9.1.0", + "node-fetch": "^2.6.1", + "ramda": "^0.27.2", + "source-map-support": "^0.5.19" + }, + "engines": { + "node": "^14.0.0 || ^16.0.0 || >=17.0.0" + } + }, + "node_modules/@cubejs-backend/templates/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@cubejs-backend/templates/node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@cubejs-backend/templates/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@cubejs-infra/post-installer": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@cubejs-infra/post-installer/-/post-installer-0.0.7.tgz", + "integrity": "sha512-9P2cY8V0mqH+FvzVM/Z43fJmuKisln4xKjZaoQi1gLygNX0wooWzGcehibqBOkeKVMg31JBRaAQrxltIaa2rYA==", + "dependencies": { + "@cubejs-backend/shared": "0.33.20", + "source-map-support": "^0.5.21" + }, + "bin": { + "post-installer": "dist/bin.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@cubejs-infra/post-installer/node_modules/@cubejs-backend/shared": { + "version": "0.33.20", + "resolved": "https://registry.npmjs.org/@cubejs-backend/shared/-/shared-0.33.20.tgz", + "integrity": "sha512-PANWng9VLr6+55QVHQv23TyDO2o1nwEWMAXd/ujUmD7AyyCHih7UllgoHYZW18vyyQm3qPxR/J7TLOACW2OcLw==", + "dependencies": { + "@oclif/color": "^0.1.2", + "bytes": "^3.1.0", + "cli-progress": "^3.9.0", + "cross-spawn": "^7.0.3", + "decompress": "^4.2.1", + "env-var": "^6.3.0", + "fs-extra": "^9.1.0", + "http-proxy-agent": "^4.0.1", + "moment-range": "^4.0.1", + "moment-timezone": "^0.5.33", + "node-fetch": "^2.6.1", + "shelljs": "^0.8.5", + "throttle-debounce": "^3.0.1", + "uuid": "^8.3.2" + }, + "engines": { + "node": "^14.0.0 || ^16.0.0 || >=17.0.0" + } + }, + "node_modules/@cubejs-infra/post-installer/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@cubejs-infra/post-installer/node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@cubejs-infra/post-installer/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@hapi/hoek": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", + "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==" + }, + "node_modules/@hapi/topo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", + "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@oclif/color": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@oclif/color/-/color-0.1.2.tgz", + "integrity": "sha512-M9o+DOrb8l603qvgz1FogJBUGLqcMFL1aFg2ZEL0FbXJofiNTLOWIeB4faeZTLwE6dt0xH9GpCVpzksMMzGbmA==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "dependencies": { + "ansi-styles": "^3.2.1", + "chalk": "^3.0.0", + "strip-ansi": "^5.2.0", + "supports-color": "^5.4.0", + "tslib": "^1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@oclif/color/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@oclif/color/node_modules/chalk/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@oclif/color/node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@oclif/color/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@oclif/color/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/@oclif/color/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@octokit/auth-token": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz", + "integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==", + "dependencies": { + "@octokit/types": "^6.0.3" + } + }, + "node_modules/@octokit/core": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz", + "integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==", + "dependencies": { + "@octokit/auth-token": "^2.4.4", + "@octokit/graphql": "^4.5.8", + "@octokit/request": "^5.6.3", + "@octokit/request-error": "^2.0.5", + "@octokit/types": "^6.0.3", + "before-after-hook": "^2.2.0", + "universal-user-agent": "^6.0.0" + } + }, + "node_modules/@octokit/endpoint": { + "version": "6.0.12", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", + "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", + "dependencies": { + "@octokit/types": "^6.0.3", + "is-plain-object": "^5.0.0", + "universal-user-agent": "^6.0.0" + } + }, + "node_modules/@octokit/graphql": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz", + "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==", + "dependencies": { + "@octokit/request": "^5.6.0", + "@octokit/types": "^6.0.3", + "universal-user-agent": "^6.0.0" + } + }, + "node_modules/@octokit/openapi-types": { + "version": "12.11.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", + "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==" + }, + "node_modules/@octokit/request": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz", + "integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==", + "dependencies": { + "@octokit/endpoint": "^6.0.1", + "@octokit/request-error": "^2.1.0", + "@octokit/types": "^6.16.1", + "is-plain-object": "^5.0.0", + "node-fetch": "^2.6.7", + "universal-user-agent": "^6.0.0" + } + }, + "node_modules/@octokit/request-error": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", + "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", + "dependencies": { + "@octokit/types": "^6.0.3", + "deprecation": "^2.0.0", + "once": "^1.4.0" + } + }, + "node_modules/@octokit/types": { + "version": "6.41.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", + "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", + "dependencies": { + "@octokit/openapi-types": "^12.11.0" + } + }, + "node_modules/@sideway/address": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz", + "integrity": "sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@sideway/formula": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", + "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==" + }, + "node_modules/@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" + }, + "node_modules/@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-0.3.4.tgz", + "integrity": "sha512-TSVh8CpnwNAsPC5wXcIyh92Bv1gq6E9cNDeeLu7Z4h8V4/qWtXJp7y42qljRkqcpmsve1iozwv1wr+3BNdILCg==" + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn-node": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", + "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", + "dependencies": { + "acorn": "^7.0.0", + "acorn-walk": "^7.0.0", + "xtend": "^4.0.2" + } + }, + "node_modules/acorn-node/node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/antlr4ts": { + "version": "0.5.0-alpha.4", + "resolved": "https://registry.npmjs.org/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz", + "integrity": "sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ==" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "dependencies": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", + "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==" + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.7.tgz", + "integrity": "sha512-LidDk/tEGDfuHW2DWh/Hgo4rmnw3cduK6ZkOI1NPFceSK3n/yAGeOsNT7FLnSGHkXj3RHGSEVkN3FsCTY6w2CQ==", + "dependencies": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.4.4", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.8.7", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.7.tgz", + "integrity": "sha512-KyDvZYxAzkC0Aj2dAPyDzi2Ym15e5JKZSK+maI7NAwSqofvuFglbSsxE7wUOvTg9oFVnHMzVzBKcqEb4PJgtOA==", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.4.4", + "core-js-compat": "^3.33.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.4.tgz", + "integrity": "sha512-S/x2iOCvDaCASLYsOOgWOq4bCfKYVqvO/uxjkaYyZ3rVsVE3CeAI/c84NpyuBBymEgNvHgjEot3a9/Z/kXvqsg==", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.4.4" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/before-after-hook": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", + "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==" + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/binaryextensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-2.3.0.tgz", + "integrity": "sha512-nAihlQsYGyc5Bwq6+EsubvANYGExeJKHDO3RjnvwU042fawQTQfM3Kxn7IHUXQOz4bzfwsGYYHGSvXyW4zOGLg==", + "engines": { + "node": ">=0.8" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/bl": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz", + "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==", + "dependencies": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" + }, + "node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==" + }, + "node_modules/browserslist": { + "version": "4.22.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", + "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001565", + "electron-to-chromium": "^1.4.601", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "dependencies": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "node_modules/buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "engines": { + "node": "*" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, + "node_modules/buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==" + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", + "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", + "dependencies": { + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.1", + "set-function-length": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001576", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001576.tgz", + "integrity": "sha512-ff5BdakGe2P3SQsMsiqmt1Lc8221NR1VzHj5jXN5vBny9A6fpze94HiVV/n7XRosOlsShJcvMv5mdnpjOGCEgg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chrono-node": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/chrono-node/-/chrono-node-2.7.4.tgz", + "integrity": "sha512-gk2xUWroQftZW3Z9mDqD3/HZW1d7fxSf0S0rNxOCfY+uUQP1FuuEcb5ulFcsEWSOQvzl02dqTeY1RK+zmc0WOQ==", + "dependencies": { + "dayjs": "^1.10.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-progress": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/cli-progress/-/cli-progress-3.12.0.tgz", + "integrity": "sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==", + "dependencies": { + "string-width": "^4.2.3" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cluster-key-slot": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", + "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/codesandbox-import-util-types": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/codesandbox-import-util-types/-/codesandbox-import-util-types-2.2.3.tgz", + "integrity": "sha512-Qj00p60oNExthP2oR3vvXmUGjukij+rxJGuiaKM6tyUmSyimdZsqHI/TUvFFClAffk9s7hxGnQgWQ8KCce27qQ==" + }, + "node_modules/codesandbox-import-utils": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/codesandbox-import-utils/-/codesandbox-import-utils-2.2.3.tgz", + "integrity": "sha512-ymtmcgZKU27U+nM2qUb21aO8Ut/u2S9s6KorOgG81weP+NA0UZkaHKlaRqbLJ9h4i/4FLvwmEXYAnTjNmp6ogg==", + "dependencies": { + "codesandbox-import-util-types": "^2.2.3", + "istextorbinary": "^2.2.1", + "lz-string": "^1.4.4" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" + }, + "node_modules/core-js-compat": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.35.0.tgz", + "integrity": "sha512-5blwFAddknKeNgsjBzilkdQ0+YK8L1PfqPYq40NOYMYFSS38qj+hpTcLLWwpIwA2A5bje/x5jmVn2tzUMg9IVw==", + "dependencies": { + "browserslist": "^4.22.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "node_modules/cron-parser": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-3.5.0.tgz", + "integrity": "sha512-wyVZtbRs6qDfFd8ap457w3XVntdvqcwBGxBoTvJQH9KGVKL/fB+h2k3C8AqiVxvUQKN1Ps/Ns46CNViOpVDhfQ==", + "dependencies": { + "is-nan": "^1.3.2", + "luxon": "^1.26.0" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/csv-write-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/csv-write-stream/-/csv-write-stream-2.0.0.tgz", + "integrity": "sha512-QTraH6FOYfM5f+YGwx71hW1nR9ZjlWri67/D4CWtiBkdce0UAa91Vc0yyHg0CjC0NeEGnvO/tBSJkA1XF9D9GQ==", + "dependencies": { + "argparse": "^1.0.7", + "generate-object-property": "^1.0.0", + "ndjson": "^1.3.0" + }, + "bin": { + "csv-write": "cli.js" + } + }, + "node_modules/d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dependencies": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/dayjs": { + "version": "1.11.10", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", + "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==" + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.1.tgz", + "integrity": "sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ==", + "dependencies": { + "decompress-tar": "^4.0.0", + "decompress-tarbz2": "^4.0.0", + "decompress-targz": "^4.0.0", + "decompress-unzip": "^4.0.1", + "graceful-fs": "^4.1.10", + "make-dir": "^1.0.0", + "pify": "^2.3.0", + "strip-dirs": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-tar": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz", + "integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==", + "dependencies": { + "file-type": "^5.2.0", + "is-stream": "^1.1.0", + "tar-stream": "^1.5.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-tarbz2": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz", + "integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==", + "dependencies": { + "decompress-tar": "^4.1.0", + "file-type": "^6.1.0", + "is-stream": "^1.1.0", + "seek-bzip": "^1.0.5", + "unbzip2-stream": "^1.0.9" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-tarbz2/node_modules/file-type": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-6.2.0.tgz", + "integrity": "sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==", + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-targz": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.1.tgz", + "integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==", + "dependencies": { + "decompress-tar": "^4.1.1", + "file-type": "^5.2.0", + "is-stream": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-unzip": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz", + "integrity": "sha512-1fqeluvxgnn86MOh66u8FjbtJpAFv5wgCT9Iw8rcBqQcCo5tO8eiJw7NNTrvt9n4CRBVq7CstiS922oPgyGLrw==", + "dependencies": { + "file-type": "^3.8.0", + "get-stream": "^2.2.0", + "pify": "^2.3.0", + "yauzl": "^2.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-unzip/node_modules/file-type": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", + "integrity": "sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-data-property": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", + "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "dependencies": { + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/del": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/del/-/del-6.1.1.tgz", + "integrity": "sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==", + "dependencies": { + "globby": "^11.0.1", + "graceful-fs": "^4.2.4", + "is-glob": "^4.0.1", + "is-path-cwd": "^2.2.0", + "is-path-inside": "^3.0.2", + "p-map": "^4.0.0", + "rimraf": "^3.0.2", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/del/node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/denque": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz", + "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/deprecation": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/editions": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/editions/-/editions-2.3.1.tgz", + "integrity": "sha512-ptGvkwTvGdGfC0hfhKg0MT+TRLRKGtUiWGBInxOm5pz7ssADezahjCUaYuZ8Dr+C05FW0AECIIPt4WBxVINEhA==", + "dependencies": { + "errlop": "^2.0.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=0.8" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/electron-to-chromium": { + "version": "1.4.623", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.623.tgz", + "integrity": "sha512-lKoz10iCYlP1WtRYdh5MvocQPWVRoI7ysp6qf18bmeBgR8abE6+I2CsfyNKztRDZvhdWc+krKT6wS7Neg8sw3A==" + }, + "node_modules/elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/env-var": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/env-var/-/env-var-6.3.0.tgz", + "integrity": "sha512-gaNzDZuVaJQJlP2SigAZLu/FieZN5MzdN7lgHNehESwlRanHwGQ/WUtJ7q//dhrj3aGBZM45yEaKOuvSJaf4mA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/errlop": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/errlop/-/errlop-2.2.0.tgz", + "integrity": "sha512-e64Qj9+4aZzjzzFpZC7p5kmm/ccCrbLhAJplhsDXQFs87XTsXwOpH4s1Io2s90Tau/8r2j9f4l/thhDevRjzxw==", + "engines": { + "node": ">=0.8" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/es5-ext": { + "version": "0.10.53", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", + "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", + "dependencies": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.3", + "next-tick": "~1.0.0" + } + }, + "node_modules/es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", + "dependencies": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "dependencies": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express-graphql": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/express-graphql/-/express-graphql-0.12.0.tgz", + "integrity": "sha512-DwYaJQy0amdy3pgNtiTDuGGM2BLdj+YO2SgbKoLliCfuHv3VVTt7vNG/ZqK2hRYjtYHE2t2KB705EU94mE64zg==", + "deprecated": "This package is no longer maintained. We recommend using `graphql-http` instead. Please consult the migration document https://github.com/graphql/graphql-http#migrating-express-grpahql.", + "dependencies": { + "accepts": "^1.3.7", + "content-type": "^1.0.4", + "http-errors": "1.8.0", + "raw-body": "^2.4.1" + }, + "engines": { + "node": ">= 10.x" + }, + "peerDependencies": { + "graphql": "^14.7.0 || ^15.3.0" + } + }, + "node_modules/express-graphql/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express-graphql/node_modules/http-errors": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.0.tgz", + "integrity": "sha512-4I8r0C5JDhT5VkvI47QktDW75rNlGVsUf/8hzjCC/wkWI/jdTRmBb9aI7erSG82r1bjKY3F6k28WnsVxB1C73A==", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express-graphql/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express-graphql/node_modules/toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/ext": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", + "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", + "dependencies": { + "type": "^2.7.2" + } + }, + "node_modules/ext/node_modules/type": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", + "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==" + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", + "engines": [ + "node >=0.6.0" + ] + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "node_modules/fastq": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.16.0.tgz", + "integrity": "sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA==", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/file-type": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", + "integrity": "sha512-Iq1nJ6D2+yIO4c8HHg4fyVb8mAJieo1Oloy1mLLaB2PvezNedhBVm+QU7g0qM42aiMbRXTxKKwGD17rjKNJYVQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/flatbuffers": { + "version": "23.3.3", + "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-23.3.3.tgz", + "integrity": "sha512-jmreOaAT1t55keaf+Z259Tvh8tR/Srry9K8dgCgvizhKSEr6gLGgaOJI2WFL5fkOpGOGRZwxUrlFn0GCmXUy6g==" + }, + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "engines": { + "node": "*" + } + }, + "node_modules/form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/generate-object-property": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha512-TuOwZWgJ2VAMEGJvAyPWvpqxSANF0LDpmyHauMjFYzaACvn+QTT/AZomvPCzVBV7yDN3OmwHQ5OvHaeLKre3JQ==", + "dependencies": { + "is-property": "^1.0.0" + } + }, + "node_modules/generic-pool": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz", + "integrity": "sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", + "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", + "dependencies": { + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-stream": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", + "integrity": "sha512-AUGhbbemXxrZJRD5cDvKtQxLuYaIbNtDTK8YqupCI393Q2KSTreEsLUN3ZxAWFGiKTzL6nKuzfcIvieflUX9qA==", + "dependencies": { + "object-assign": "^4.0.1", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "dependencies": { + "assert-plus": "^1.0.0" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "node_modules/graphql": { + "version": "15.8.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.8.0.tgz", + "integrity": "sha512-5gghUc24tP9HRznNpV2+FIoq3xKkj5dTQqf4v0CpdPbFVwFkWoxOM+o+2OC9ZSvjEMTjfmG9QT+gcvggTwW1zw==", + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/graphql-scalars": { + "version": "1.22.4", + "resolved": "https://registry.npmjs.org/graphql-scalars/-/graphql-scalars-1.22.4.tgz", + "integrity": "sha512-ILnv7jq5VKHLUyoaTFX7lgYrjCd6vTee9i8/B+D4zJKJT5TguOl0KkpPEbXHjmeor8AZYrVsrYUHdqRBMX1pjA==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" + } + }, + "node_modules/graphql-scalars/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", + "engines": { + "node": ">=4" + } + }, + "node_modules/har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "deprecated": "this library is no longer supported", + "dependencies": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", + "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "dependencies": { + "get-intrinsic": "^1.2.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "node_modules/hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + }, + "engines": { + "node": ">=0.8", + "npm": ">=1.3.7" + } + }, + "node_modules/humps": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/humps/-/humps-2.0.1.tgz", + "integrity": "sha512-E0eIbrFWUhwfXJmsbdjRQFQPrl5pTEoKlz163j1mTqqUnU9PgR4AgB8AIITzuB3vLBdxZXyZ9TDIrwB2OASz4g==" + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/ignore": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", + "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/inflection": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.4.tgz", + "integrity": "sha512-6I/HUDeYFfuNCVS3td055BaXBwKYuzw7K3ExVMStBowKo9oOAMJIXIHvdyR3iboTCp1b+1i5DSkIZTcwIktuDw==", + "engines": [ + "node >= 0.4.0" + ] + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/ioredis": { + "version": "4.28.5", + "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-4.28.5.tgz", + "integrity": "sha512-3GYo0GJtLqgNXj4YhrisLaNNvWSNwSS2wS4OELGfGxH8I69+XfNdnmV1AyN+ZqMh0i7eX+SWjrwFKDBDgfBC1A==", + "dependencies": { + "cluster-key-slot": "^1.1.0", + "debug": "^4.3.1", + "denque": "^1.1.0", + "lodash.defaults": "^4.2.0", + "lodash.flatten": "^4.4.0", + "lodash.isarguments": "^3.1.0", + "p-map": "^2.1.0", + "redis-commands": "1.7.0", + "redis-errors": "^1.2.0", + "redis-parser": "^3.0.0", + "standard-as-callback": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ioredis" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dependencies": { + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-nan": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", + "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-natural-number": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", + "integrity": "sha512-Y4LTamMe0DDQIIAlaer9eKebAlDSV6huy+TWhJVPlzZh2o4tRP5SQWFlLn5N0To4mDD22/qdOq+veo1cSISLgQ==" + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==" + }, + "node_modules/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" + }, + "node_modules/istextorbinary": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-2.6.0.tgz", + "integrity": "sha512-+XRlFseT8B3L9KyjxxLjfXSLMuErKDsd8DBNrsaxoViABMEZlOSCstwmw0qpoFX3+U6yWU1yhLudAe6/lETGGA==", + "dependencies": { + "binaryextensions": "^2.1.2", + "editions": "^2.2.0", + "textextensions": "^2.5.0" + }, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/iterall": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/iterall/-/iterall-1.3.0.tgz", + "integrity": "sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg==" + }, + "node_modules/joi": { + "version": "17.11.0", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.11.0.tgz", + "integrity": "sha512-NgB+lZLNoqISVy1rZocE9PZI36bL/77ie924Ri43yEvi9GUUMPeyVIr8KdFTMUlby1p0PBYMk9spIxEUQYqrJQ==", + "dependencies": { + "@hapi/hoek": "^9.0.0", + "@hapi/topo": "^5.0.0", + "@sideway/address": "^4.1.3", + "@sideway/formula": "^3.0.1", + "@sideway/pinpoint": "^2.0.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/js-yaml/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==" + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsprim": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", + "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jwk-to-pem": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/jwk-to-pem/-/jwk-to-pem-2.0.5.tgz", + "integrity": "sha512-L90jwellhO8jRKYwbssU9ifaMVqajzj3fpRjDKcsDzrslU9syRbFqfkXtT4B89HYAap+xsxNcxgBSB09ig+a7A==", + "dependencies": { + "asn1.js": "^5.3.0", + "elliptic": "^6.5.4", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==" + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" + }, + "node_modules/lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==" + }, + "node_modules/lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==" + }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, + "node_modules/lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/luxon": { + "version": "1.28.1", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-1.28.1.tgz", + "integrity": "sha512-gYHAa180mKrNIUJCbwpmD0aTu9kV0dREDrwNnuyFAsO1Wt0EVYSZelPnJlbj9HplzXX/YWXHFTL45kvZ53M0pw==", + "engines": { + "node": "*" + } + }, + "node_modules/lz-string": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "bin": { + "lz-string": "bin/bin.js" + } + }, + "node_modules/make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "dependencies": { + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/make-dir/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "engines": { + "node": ">=4" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==" + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/moment": { + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", + "engines": { + "node": "*" + } + }, + "node_modules/moment-range": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/moment-range/-/moment-range-4.0.2.tgz", + "integrity": "sha512-n8sceWwSTjmz++nFHzeNEUsYtDqjgXgcOBzsHi+BoXQU2FW+eU92LUaK8gqOiSu5PG57Q9sYj1Fz4LRDj4FtKA==", + "dependencies": { + "es6-symbol": "^3.1.0" + }, + "engines": { + "node": "*" + }, + "peerDependencies": { + "moment": ">= 2" + } + }, + "node_modules/moment-timezone": { + "version": "0.5.44", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.44.tgz", + "integrity": "sha512-nv3YpzI/8lkQn0U6RkLd+f0W/zy/JnoR5/EyPz/dNkPTBjA2jNLCVxaiQ8QpeLymhSZvX0wCL5s27NQWdOPwAw==", + "dependencies": { + "moment": "^2.29.4" + }, + "engines": { + "node": "*" + } + }, + "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==" + }, + "node_modules/ndjson": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/ndjson/-/ndjson-1.5.0.tgz", + "integrity": "sha512-hUPLuaziboGjNF7wHngkgVc0FOclR8dDk/HfEvTtDr/iUrqBWiRcRSTK3/nLOqKH33th714BrMmTPtObI9gZxQ==", + "dependencies": { + "json-stringify-safe": "^5.0.1", + "minimist": "^1.2.0", + "split2": "^2.1.0", + "through2": "^2.0.3" + }, + "bin": { + "ndjson": "cli.js" + } + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha512-mc/caHeUcdjnC/boPWJefDr4KUIWQNv+tlnFnJd38QMou86QtxQzBJfxgGRzvx8jazYRqrVlaHarfO72uNxPOg==" + }, + "node_modules/nexus": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/nexus/-/nexus-1.3.0.tgz", + "integrity": "sha512-w/s19OiNOs0LrtP7pBmD9/FqJHvZLmCipVRt6v1PM8cRUYIbhEswyNKGHVoC4eHZGPSnD+bOf5A3+gnbt0A5/A==", + "dependencies": { + "iterall": "^1.3.0", + "tslib": "^2.0.3" + }, + "peerDependencies": { + "graphql": "15.x || 16.x" + } + }, + "node_modules/nexus/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/node-dijkstra": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/node-dijkstra/-/node-dijkstra-2.5.0.tgz", + "integrity": "sha512-2REYb1lo8yDRAY1gsdhjwQdGVSh47VI5Z5wS8sCqydO/P1OVAKOwLuV1fDxNLvbrtMspW7k2UZ2JKIKP06hl+A==" + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "engines": { + "node": "*" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==" + }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", + "dependencies": { + "pinkie": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/promise-timeout": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/promise-timeout/-/promise-timeout-1.3.0.tgz", + "integrity": "sha512-5yANTE0tmi5++POym6OgtFmwfDvOXABD9oj/jLQr5GPEyuNEb7jH4wbbANJceJid49jwhi1RddxnhnEAb/doqg==" + }, + "node_modules/psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/ramda": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.27.2.tgz", + "integrity": "sha512-SbiLPU40JuJniHexQSAgad32hfwd+DRUdwF2PlVuI5RZD0/vahUco7R8vD86J/tcEKKF9vZrUVwgtmGCqlCKyA==" + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", + "dependencies": { + "resolve": "^1.1.6" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/redis": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/redis/-/redis-3.1.2.tgz", + "integrity": "sha512-grn5KoZLr/qrRQVwoSkmzdbw6pwF+/rwODtrOr6vuBRiR/f3rjSTGupbF90Zpqm2oenix8Do6RV7pYEkGwlKkw==", + "dependencies": { + "denque": "^1.5.0", + "redis-commands": "^1.7.0", + "redis-errors": "^1.2.0", + "redis-parser": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-redis" + } + }, + "node_modules/redis-commands": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.7.0.tgz", + "integrity": "sha512-nJWqw3bTFy21hX/CPKHth6sfhZbdiHP6bTawSgQBlKOVRG7EZkfHbbHwQJnrE4vsQf0CMNE+3gJ4Fmm16vdVlQ==" + }, + "node_modules/redis-errors": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", + "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==", + "engines": { + "node": ">=4" + } + }, + "node_modules/redis-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", + "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", + "dependencies": { + "redis-errors": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", + "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + }, + "node_modules/regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, + "node_modules/regexpu-core": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", + "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "dependencies": { + "@babel/regjsgen": "^0.8.0", + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.1.0", + "regjsparser": "^0.9.1", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsparser": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/request-promise": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.6.tgz", + "integrity": "sha512-HCHI3DJJUakkOr8fNoCc73E5nU5bqITjOYFMDrKHYOXWXrgD/SBaC7LjwuPymUprRyuF06UK7hd/lMHkmUXglQ==", + "deprecated": "request-promise has been deprecated because it extends the now deprecated request package, see https://github.com/request/request/issues/3142", + "dependencies": { + "bluebird": "^3.5.0", + "request-promise-core": "1.1.4", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" + }, + "engines": { + "node": ">=0.10.0" + }, + "peerDependencies": { + "request": "^2.34" + } + }, + "node_modules/request-promise-core": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz", + "integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==", + "dependencies": { + "lodash": "^4.17.19" + }, + "engines": { + "node": ">=0.10.0" + }, + "peerDependencies": { + "request": "^2.34" + } + }, + "node_modules/request/node_modules/qs": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", + "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/request/node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/seek-bzip": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.6.tgz", + "integrity": "sha512-e1QtP3YL5tWww8uKaOCQ18UxIT2laNBXHjV/S2WYCiK4udiv8lkG89KRIoCjUagnAmCBurjF4zEVX2ByBbnCjQ==", + "dependencies": { + "commander": "^2.8.1" + }, + "bin": { + "seek-bunzip": "bin/seek-bunzip", + "seek-table": "bin/seek-bzip-table" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-function-length": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", + "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "dependencies": { + "define-data-property": "^1.1.1", + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, + "node_modules/shelljs": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", + "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", + "dependencies": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + }, + "bin": { + "shjs": "bin/shjs" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/split2": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-2.2.0.tgz", + "integrity": "sha512-RAb22TG39LhI31MbreBgIuKiIKhVsawfTgEGqKHTK87aG+ul/PB8Sqoi3I7kVdRWiCfrKxK3uo4/YUkpNvhPbw==", + "dependencies": { + "through2": "^2.0.2" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + }, + "node_modules/sqlstring": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", + "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/sshpk": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", + "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/standard-as-callback": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", + "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==" + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/stealthy-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha512-ZnWpYnYugiOVEY5GkcuJK1io5V8QmNYChG62gSit9pQVGErXtrKuPC55ITaVSukmMta5qpMU7vqLt2Lnni4f/g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-dirs": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz", + "integrity": "sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==", + "dependencies": { + "is-natural-number": "^4.0.1" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/syntax-error": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.4.0.tgz", + "integrity": "sha512-YPPlu67mdnHGTup2A8ff7BC2Pjq0e0Yp/IyTFN03zWO0RcK07uLcbi7C2KpGR2FvWbaB0+bfE27a+sBKebSo7w==", + "dependencies": { + "acorn-node": "^1.2.0" + } + }, + "node_modules/tar-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", + "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", + "dependencies": { + "bl": "^1.0.0", + "buffer-alloc": "^1.2.0", + "end-of-stream": "^1.0.0", + "fs-constants": "^1.0.0", + "readable-stream": "^2.3.0", + "to-buffer": "^1.1.1", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/temp-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", + "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/tempy": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tempy/-/tempy-1.0.1.tgz", + "integrity": "sha512-biM9brNqxSc04Ee71hzFbryD11nX7VPhQQY32AdDmjFvodsRFz/3ufeoTZ6uYkRFfGo188tENcASNs3vTdsM0w==", + "dependencies": { + "del": "^6.0.0", + "is-stream": "^2.0.0", + "temp-dir": "^2.0.0", + "type-fest": "^0.16.0", + "unique-string": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tempy/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/textextensions": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-2.6.0.tgz", + "integrity": "sha512-49WtAWS+tcsy93dRt6P0P3AMD2m5PvXRhuEA0kaXos5ZLlujtYmpmFsB+QvWUSxE1ZsstmYXfQ7L40+EcQgpAQ==", + "engines": { + "node": ">=0.8" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/throttle-debounce": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-3.0.1.tgz", + "integrity": "sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg==", + "engines": { + "node": ">=10" + } + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" + }, + "node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/to-buffer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==" + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" + }, + "node_modules/type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" + }, + "node_modules/type-fest": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", + "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/unbzip2-stream": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", + "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", + "dependencies": { + "buffer": "^5.2.1", + "through": "^2.3.8" + } + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", + "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "dependencies": { + "crypto-random-string": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/universal-user-agent": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz", + "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==" + }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/verror/node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + }, + "dependencies": { + "@ampproject/remapping": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "requires": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@babel/code-frame": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "requires": { + "@babel/highlight": "^7.23.4", + "chalk": "^2.4.2" + } + }, + "@babel/compat-data": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", + "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==" + }, + "@babel/core": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.7.tgz", + "integrity": "sha512-+UpDgowcmqe36d4NwqvKsyPMlOLNGMsfMmQ5WGCu+siCe3t3dfe9njrzGfdN4qq+bcNUt0+Vw6haRxBOycs4dw==", + "requires": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helpers": "^7.23.7", + "@babel/parser": "^7.23.6", + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.7", + "@babel/types": "^7.23.6", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + } + }, + "@babel/generator": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", + "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", + "requires": { + "@babel/types": "^7.23.6", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", + "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz", + "integrity": "sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==", + "requires": { + "@babel/types": "^7.22.15" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", + "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", + "requires": { + "@babel/compat-data": "^7.23.5", + "@babel/helper-validator-option": "^7.23.5", + "browserslist": "^4.22.2", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + } + }, + "@babel/helper-create-class-features-plugin": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.23.7.tgz", + "integrity": "sha512-xCoqR/8+BoNnXOY7RVSgv6X+o7pmT5q1d+gGcRlXYkI+9B31glE4jeejhKVpA04O1AtzOt7OSQ6VYKP5FcRl9g==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-member-expression-to-functions": "^7.23.0", + "@babel/helper-optimise-call-expression": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.20", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "semver": "^6.3.1" + } + }, + "@babel/helper-create-regexp-features-plugin": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz", + "integrity": "sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "regexpu-core": "^5.3.1", + "semver": "^6.3.1" + } + }, + "@babel/helper-define-polyfill-provider": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.4.tgz", + "integrity": "sha512-QcJMILQCu2jm5TFPGA3lCpJJTeEP+mqeXooG/NZbg/h5FTFi6V0+99ahlRsW8/kRLyb24LZVCCiclDedhLKcBA==", + "requires": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + } + }, + "@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==" + }, + "@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "requires": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz", + "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==", + "requires": { + "@babel/types": "^7.23.0" + } + }, + "@babel/helper-module-imports": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "requires": { + "@babel/types": "^7.22.15" + } + }, + "@babel/helper-module-transforms": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", + "requires": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz", + "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==", + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==" + }, + "@babel/helper-remap-async-to-generator": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz", + "integrity": "sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-wrap-function": "^7.22.20" + } + }, + "@babel/helper-replace-supers": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz", + "integrity": "sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==", + "requires": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-member-expression-to-functions": "^7.22.15", + "@babel/helper-optimise-call-expression": "^7.22.5" + } + }, + "@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz", + "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==", + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-string-parser": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", + "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==" + }, + "@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==" + }, + "@babel/helper-validator-option": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==" + }, + "@babel/helper-wrap-function": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz", + "integrity": "sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==", + "requires": { + "@babel/helper-function-name": "^7.22.5", + "@babel/template": "^7.22.15", + "@babel/types": "^7.22.19" + } + }, + "@babel/helpers": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.7.tgz", + "integrity": "sha512-6AMnjCoC8wjqBzDHkuqpa7jAKwvMo4dC+lr/TFBz+ucfulO1XMpDnwWPGBNwClOKZ8h6xn5N81W/R5OrcKtCbQ==", + "requires": { + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.7", + "@babel/types": "^7.23.6" + } + }, + "@babel/highlight": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "requires": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.6.tgz", + "integrity": "sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==" + }, + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.23.3.tgz", + "integrity": "sha512-iRkKcCqb7iGnq9+3G6rZ+Ciz5VywC4XNRHe57lKM+jOeYAoR0lVqdeeDRfh0tQcTfw/+vBhHn926FmQhLtlFLQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.23.3.tgz", + "integrity": "sha512-WwlxbfMNdVEpQjZmK5mhm7oSwD3dS6eU+Iwsi4Knl9wAletWem7kaRsGOG+8UEbRyqxY4SS5zvtfXwX+jMxUwQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-transform-optional-chaining": "^7.23.3" + } + }, + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.23.7.tgz", + "integrity": "sha512-LlRT7HgaifEpQA1ZgLVOIJZZFVPWN5iReq/7/JixwBtwcoeVGDBD53ZV28rrsLYOZs1Y/EHhA8N/Z6aazHR8cw==", + "requires": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "requires": {} + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "requires": { + "@babel/helper-plugin-utils": "^7.12.13" + } + }, + "@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-syntax-import-assertions": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.23.3.tgz", + "integrity": "sha512-lPgDSU+SJLK3xmFDTV2ZRQAiM7UuUjGidwBywFavObCiZc1BeAAcMtHJKUya92hPHO+at63JJPLygilZard8jw==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-syntax-import-attributes": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.23.3.tgz", + "integrity": "sha512-pawnE0P9g10xgoP7yKr6CK63K2FMsTE+FZidZO/1PwRdzmAPVs+HS1mAURUsgaoxammTJvULUdIkEK0gOcU2tA==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-arrow-functions": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.23.3.tgz", + "integrity": "sha512-NzQcQrzaQPkaEwoTm4Mhyl8jI1huEL/WWIEvudjTCMJ9aBZNpsJbMASx7EQECtQQPS/DcnFpo0FIh3LvEO9cxQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-async-generator-functions": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.7.tgz", + "integrity": "sha512-PdxEpL71bJp1byMG0va5gwQcXHxuEYC/BgI/e88mGTtohbZN28O5Yit0Plkkm/dBzCF/BxmbNcses1RH1T+urA==", + "requires": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-remap-async-to-generator": "^7.22.20", + "@babel/plugin-syntax-async-generators": "^7.8.4" + } + }, + "@babel/plugin-transform-async-to-generator": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.23.3.tgz", + "integrity": "sha512-A7LFsKi4U4fomjqXJlZg/u0ft/n8/7n7lpffUP/ZULx/DtV9SGlNKZolHH6PE8Xl1ngCc0M11OaeZptXVkfKSw==", + "requires": { + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-remap-async-to-generator": "^7.22.20" + } + }, + "@babel/plugin-transform-block-scoped-functions": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.23.3.tgz", + "integrity": "sha512-vI+0sIaPIO6CNuM9Kk5VmXcMVRiOpDh7w2zZt9GXzmE/9KD70CUEVhvPR/etAeNK/FAEkhxQtXOzVF3EuRL41A==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-block-scoping": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.4.tgz", + "integrity": "sha512-0QqbP6B6HOh7/8iNR4CQU2Th/bbRtBp4KS9vcaZd1fZ0wSh5Fyssg0UCIHwxh+ka+pNDREbVLQnHCMHKZfPwfw==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-class-properties": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.23.3.tgz", + "integrity": "sha512-uM+AN8yCIjDPccsKGlw271xjJtGii+xQIF/uMPS8H15L12jZTsLfF4o5vNO7d/oUguOyfdikHGc/yi9ge4SGIg==", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-class-static-block": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.23.4.tgz", + "integrity": "sha512-nsWu/1M+ggti1SOALj3hfx5FXzAY06fwPJsUZD4/A5e1bWi46VUIWtD+kOX6/IdhXGsXBWllLFDSnqSCdUNydQ==", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + } + }, + "@babel/plugin-transform-classes": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.23.5.tgz", + "integrity": "sha512-jvOTR4nicqYC9yzOHIhXG5emiFEOpappSJAl73SDSEDcybD+Puuze8Tnpb9p9qEyYup24tq891gkaygIFvWDqg==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-optimise-call-expression": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.20", + "@babel/helper-split-export-declaration": "^7.22.6", + "globals": "^11.1.0" + } + }, + "@babel/plugin-transform-computed-properties": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.23.3.tgz", + "integrity": "sha512-dTj83UVTLw/+nbiHqQSFdwO9CbTtwq1DsDqm3CUEtDrZNET5rT5E6bIdTlOftDTDLMYxvxHNEYO4B9SLl8SLZw==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/template": "^7.22.15" + } + }, + "@babel/plugin-transform-destructuring": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.3.tgz", + "integrity": "sha512-n225npDqjDIr967cMScVKHXJs7rout1q+tt50inyBCPkyZ8KxeI6d+GIbSBTT/w/9WdlWDOej3V9HE5Lgk57gw==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-dotall-regex": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.23.3.tgz", + "integrity": "sha512-vgnFYDHAKzFaTVp+mneDsIEbnJ2Np/9ng9iviHw3P/KVcgONxpNULEW/51Z/BaFojG2GI2GwwXck5uV1+1NOYQ==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-duplicate-keys": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.23.3.tgz", + "integrity": "sha512-RrqQ+BQmU3Oyav3J+7/myfvRCq7Tbz+kKLLshUmMwNlDHExbGL7ARhajvoBJEvc+fCguPPu887N+3RRXBVKZUA==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-dynamic-import": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.23.4.tgz", + "integrity": "sha512-V6jIbLhdJK86MaLh4Jpghi8ho5fGzt3imHOBu/x0jlBaPYqDoWz4RDXjmMOfnh+JWNaQleEAByZLV0QzBT4YQQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + } + }, + "@babel/plugin-transform-exponentiation-operator": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.23.3.tgz", + "integrity": "sha512-5fhCsl1odX96u7ILKHBj4/Y8vipoqwsJMh4csSA8qFfxrZDEA4Ssku2DyNvMJSmZNOEBT750LfFPbtrnTP90BQ==", + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-export-namespace-from": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.23.4.tgz", + "integrity": "sha512-GzuSBcKkx62dGzZI1WVgTWvkkz84FZO5TC5T8dl/Tht/rAla6Dg/Mz9Yhypg+ezVACf/rgDuQt3kbWEv7LdUDQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + } + }, + "@babel/plugin-transform-for-of": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.23.6.tgz", + "integrity": "sha512-aYH4ytZ0qSuBbpfhuofbg/e96oQ7U2w1Aw/UQmKT+1l39uEhUPoFS3fHevDc1G0OvewyDudfMKY1OulczHzWIw==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + } + }, + "@babel/plugin-transform-function-name": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.23.3.tgz", + "integrity": "sha512-I1QXp1LxIvt8yLaib49dRW5Okt7Q4oaxao6tFVKS/anCdEOMtYwWVKoiOA1p34GOWIZjUK0E+zCp7+l1pfQyiw==", + "requires": { + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-json-strings": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.23.4.tgz", + "integrity": "sha512-81nTOqM1dMwZ/aRXQ59zVubN9wHGqk6UtqRK+/q+ciXmRy8fSolhGVvG09HHRGo4l6fr/c4ZhXUQH0uFW7PZbg==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-json-strings": "^7.8.3" + } + }, + "@babel/plugin-transform-literals": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.23.3.tgz", + "integrity": "sha512-wZ0PIXRxnwZvl9AYpqNUxpZ5BiTGrYt7kueGQ+N5FiQ7RCOD4cm8iShd6S6ggfVIWaJf2EMk8eRzAh52RfP4rQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-logical-assignment-operators": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.23.4.tgz", + "integrity": "sha512-Mc/ALf1rmZTP4JKKEhUwiORU+vcfarFVLfcFiolKUo6sewoxSEgl36ak5t+4WamRsNr6nzjZXQjM35WsU+9vbg==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + } + }, + "@babel/plugin-transform-member-expression-literals": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.23.3.tgz", + "integrity": "sha512-sC3LdDBDi5x96LA+Ytekz2ZPk8i/Ck+DEuDbRAll5rknJ5XRTSaPKEYwomLcs1AA8wg9b3KjIQRsnApj+q51Ag==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-modules-amd": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.23.3.tgz", + "integrity": "sha512-vJYQGxeKM4t8hYCKVBlZX/gtIY2I7mRGFNcm85sgXGMTBcoV3QdVtdpbcWEbzbfUIUZKwvgFT82mRvaQIebZzw==", + "requires": { + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.3.tgz", + "integrity": "sha512-aVS0F65LKsdNOtcz6FRCpE4OgsP2OFnW46qNxNIX9h3wuzaNcSQsJysuMwqSibC98HPrf2vCgtxKNwS0DAlgcA==", + "requires": { + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-simple-access": "^7.22.5" + } + }, + "@babel/plugin-transform-modules-systemjs": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.3.tgz", + "integrity": "sha512-ZxyKGTkF9xT9YJuKQRo19ewf3pXpopuYQd8cDXqNzc3mUNbOME0RKMoZxviQk74hwzfQsEe66dE92MaZbdHKNQ==", + "requires": { + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20" + } + }, + "@babel/plugin-transform-modules-umd": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.23.3.tgz", + "integrity": "sha512-zHsy9iXX2nIsCBFPud3jKn1IRPWg3Ing1qOZgeKV39m1ZgIdpJqvlWVeiHBZC6ITRG0MfskhYe9cLgntfSFPIg==", + "requires": { + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz", + "integrity": "sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-new-target": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.23.3.tgz", + "integrity": "sha512-YJ3xKqtJMAT5/TIZnpAR3I+K+WaDowYbN3xyxI8zxx/Gsypwf9B9h0VB+1Nh6ACAAPRS5NSRje0uVv5i79HYGQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.23.4.tgz", + "integrity": "sha512-jHE9EVVqHKAQx+VePv5LLGHjmHSJR76vawFPTdlxR/LVJPfOEGxREQwQfjuZEOPTwG92X3LINSh3M40Rv4zpVA==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + } + }, + "@babel/plugin-transform-numeric-separator": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.23.4.tgz", + "integrity": "sha512-mps6auzgwjRrwKEZA05cOwuDc9FAzoyFS4ZsG/8F43bTLf/TgkJg7QXOrPO1JO599iA3qgK9MXdMGOEC8O1h6Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + } + }, + "@babel/plugin-transform-object-rest-spread": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.23.4.tgz", + "integrity": "sha512-9x9K1YyeQVw0iOXJlIzwm8ltobIIv7j2iLyP2jIhEbqPRQ7ScNgwQufU2I0Gq11VjyG4gI4yMXt2VFags+1N3g==", + "requires": { + "@babel/compat-data": "^7.23.3", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.23.3" + } + }, + "@babel/plugin-transform-object-super": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.23.3.tgz", + "integrity": "sha512-BwQ8q0x2JG+3lxCVFohg+KbQM7plfpBwThdW9A6TMtWwLsbDA01Ek2Zb/AgDN39BiZsExm4qrXxjk+P1/fzGrA==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.20" + } + }, + "@babel/plugin-transform-optional-catch-binding": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.23.4.tgz", + "integrity": "sha512-XIq8t0rJPHf6Wvmbn9nFxU6ao4c7WhghTR5WyV8SrJfUFzyxhCm4nhC+iAp3HFhbAKLfYpgzhJ6t4XCtVwqO5A==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + } + }, + "@babel/plugin-transform-optional-chaining": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.4.tgz", + "integrity": "sha512-ZU8y5zWOfjM5vZ+asjgAPwDaBjJzgufjES89Rs4Lpq63O300R/kOz30WCLo6BxxX6QVEilwSlpClnG5cZaikTA==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + } + }, + "@babel/plugin-transform-parameters": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.23.3.tgz", + "integrity": "sha512-09lMt6UsUb3/34BbECKVbVwrT9bO6lILWln237z7sLaWnMsTi7Yc9fhX5DLpkJzAGfaReXI22wP41SZmnAA3Vw==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-private-methods": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.23.3.tgz", + "integrity": "sha512-UzqRcRtWsDMTLrRWFvUBDwmw06tCQH9Rl1uAjfh6ijMSmGYQ+fpdB+cnqRC8EMh5tuuxSv0/TejGL+7vyj+50g==", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-private-property-in-object": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.23.4.tgz", + "integrity": "sha512-9G3K1YqTq3F4Vt88Djx1UZ79PDyj+yKRnUy7cZGSMe+a7jkwD259uKKuUzQlPkGam7R+8RJwh5z4xO27fA1o2A==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + } + }, + "@babel/plugin-transform-property-literals": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.23.3.tgz", + "integrity": "sha512-jR3Jn3y7cZp4oEWPFAlRsSWjxKe4PZILGBSd4nis1TsC5qeSpb+nrtihJuDhNI7QHiVbUaiXa0X2RZY3/TI6Nw==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-regenerator": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.23.3.tgz", + "integrity": "sha512-KP+75h0KghBMcVpuKisx3XTu9Ncut8Q8TuvGO4IhY+9D5DFEckQefOuIsB/gQ2tG71lCke4NMrtIPS8pOj18BQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "regenerator-transform": "^0.15.2" + } + }, + "@babel/plugin-transform-reserved-words": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.23.3.tgz", + "integrity": "sha512-QnNTazY54YqgGxwIexMZva9gqbPa15t/x9VS+0fsEFWplwVpXYZivtgl43Z1vMpc1bdPP2PP8siFeVcnFvA3Cg==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-shorthand-properties": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.23.3.tgz", + "integrity": "sha512-ED2fgqZLmexWiN+YNFX26fx4gh5qHDhn1O2gvEhreLW2iI63Sqm4llRLCXALKrCnbN4Jy0VcMQZl/SAzqug/jg==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-spread": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.23.3.tgz", + "integrity": "sha512-VvfVYlrlBVu+77xVTOAoxQ6mZbnIq5FM0aGBSFEcIh03qHf+zNqA4DC/3XMUozTg7bZV3e3mZQ0i13VB6v5yUg==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + } + }, + "@babel/plugin-transform-sticky-regex": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.23.3.tgz", + "integrity": "sha512-HZOyN9g+rtvnOU3Yh7kSxXrKbzgrm5X4GncPY1QOquu7epga5MxKHVpYu2hvQnry/H+JjckSYRb93iNfsioAGg==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-template-literals": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.23.3.tgz", + "integrity": "sha512-Flok06AYNp7GV2oJPZZcP9vZdszev6vPBkHLwxwSpaIqx75wn6mUd3UFWsSsA0l8nXAKkyCmL/sR02m8RYGeHg==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-typeof-symbol": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.23.3.tgz", + "integrity": "sha512-4t15ViVnaFdrPC74be1gXBSMzXk3B4Us9lP7uLRQHTFpV5Dvt33pn+2MyyNxmN3VTTm3oTrZVMUmuw3oBnQ2oQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-unicode-escapes": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.23.3.tgz", + "integrity": "sha512-OMCUx/bU6ChE3r4+ZdylEqAjaQgHAgipgW8nsCfu5pGqDcFytVd91AwRvUJSBZDz0exPGgnjoqhgRYLRjFZc9Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-unicode-property-regex": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.23.3.tgz", + "integrity": "sha512-KcLIm+pDZkWZQAFJ9pdfmh89EwVfmNovFBcXko8szpBeF8z68kWIPeKlmSOkT9BXJxs2C0uk+5LxoxIv62MROA==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-unicode-regex": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.23.3.tgz", + "integrity": "sha512-wMHpNA4x2cIA32b/ci3AfwNgheiva2W0WUKWTK7vBHBhDKfPsc5cFGNWm69WBqpwd86u1qwZ9PWevKqm1A3yAw==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-unicode-sets-regex": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.23.3.tgz", + "integrity": "sha512-W7lliA/v9bNR83Qc3q1ip9CQMZ09CcHDbHfbLRDNuAhn1Mvkr1ZNF7hPmztMQvtTGVLJ9m8IZqWsTkXOml8dbw==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/preset-env": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.23.7.tgz", + "integrity": "sha512-SY27X/GtTz/L4UryMNJ6p4fH4nsgWbz84y9FE0bQeWJP6O5BhgVCt53CotQKHCOeXJel8VyhlhujhlltKms/CA==", + "requires": { + "@babel/compat-data": "^7.23.5", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-option": "^7.23.5", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.23.3", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.23.3", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.23.7", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.23.3", + "@babel/plugin-syntax-import-attributes": "^7.23.3", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.23.3", + "@babel/plugin-transform-async-generator-functions": "^7.23.7", + "@babel/plugin-transform-async-to-generator": "^7.23.3", + "@babel/plugin-transform-block-scoped-functions": "^7.23.3", + "@babel/plugin-transform-block-scoping": "^7.23.4", + "@babel/plugin-transform-class-properties": "^7.23.3", + "@babel/plugin-transform-class-static-block": "^7.23.4", + "@babel/plugin-transform-classes": "^7.23.5", + "@babel/plugin-transform-computed-properties": "^7.23.3", + "@babel/plugin-transform-destructuring": "^7.23.3", + "@babel/plugin-transform-dotall-regex": "^7.23.3", + "@babel/plugin-transform-duplicate-keys": "^7.23.3", + "@babel/plugin-transform-dynamic-import": "^7.23.4", + "@babel/plugin-transform-exponentiation-operator": "^7.23.3", + "@babel/plugin-transform-export-namespace-from": "^7.23.4", + "@babel/plugin-transform-for-of": "^7.23.6", + "@babel/plugin-transform-function-name": "^7.23.3", + "@babel/plugin-transform-json-strings": "^7.23.4", + "@babel/plugin-transform-literals": "^7.23.3", + "@babel/plugin-transform-logical-assignment-operators": "^7.23.4", + "@babel/plugin-transform-member-expression-literals": "^7.23.3", + "@babel/plugin-transform-modules-amd": "^7.23.3", + "@babel/plugin-transform-modules-commonjs": "^7.23.3", + "@babel/plugin-transform-modules-systemjs": "^7.23.3", + "@babel/plugin-transform-modules-umd": "^7.23.3", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5", + "@babel/plugin-transform-new-target": "^7.23.3", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.23.4", + "@babel/plugin-transform-numeric-separator": "^7.23.4", + "@babel/plugin-transform-object-rest-spread": "^7.23.4", + "@babel/plugin-transform-object-super": "^7.23.3", + "@babel/plugin-transform-optional-catch-binding": "^7.23.4", + "@babel/plugin-transform-optional-chaining": "^7.23.4", + "@babel/plugin-transform-parameters": "^7.23.3", + "@babel/plugin-transform-private-methods": "^7.23.3", + "@babel/plugin-transform-private-property-in-object": "^7.23.4", + "@babel/plugin-transform-property-literals": "^7.23.3", + "@babel/plugin-transform-regenerator": "^7.23.3", + "@babel/plugin-transform-reserved-words": "^7.23.3", + "@babel/plugin-transform-shorthand-properties": "^7.23.3", + "@babel/plugin-transform-spread": "^7.23.3", + "@babel/plugin-transform-sticky-regex": "^7.23.3", + "@babel/plugin-transform-template-literals": "^7.23.3", + "@babel/plugin-transform-typeof-symbol": "^7.23.3", + "@babel/plugin-transform-unicode-escapes": "^7.23.3", + "@babel/plugin-transform-unicode-property-regex": "^7.23.3", + "@babel/plugin-transform-unicode-regex": "^7.23.3", + "@babel/plugin-transform-unicode-sets-regex": "^7.23.3", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.7", + "babel-plugin-polyfill-corejs3": "^0.8.7", + "babel-plugin-polyfill-regenerator": "^0.5.4", + "core-js-compat": "^3.31.0", + "semver": "^6.3.1" + } + }, + "@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + } + }, + "@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==" + }, + "@babel/runtime": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.7.tgz", + "integrity": "sha512-w06OXVOFso7LcbzMiDGt+3X7Rh7Ho8MmgPoWU3rarH+8upf+wSU/grlGbWzQyr3DkdN6ZeuMFjpdwW0Q+HxobA==", + "requires": { + "regenerator-runtime": "^0.14.0" + } + }, + "@babel/standalone": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/standalone/-/standalone-7.23.7.tgz", + "integrity": "sha512-AsO3aIh9I4qIqK61d6nPxPAdrSuWF4FmOLej3xNIkBIZj+8XJGArQQJw6DnuUkkqbsLp1fARkXOdKiuqWgac0Q==" + }, + "@babel/template": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "requires": { + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" + } + }, + "@babel/traverse": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.7.tgz", + "integrity": "sha512-tY3mM8rH9jM0YHFGyfC0/xf+SB5eKUu7HPj7/k3fpi9dAlsMc5YbQvDi0Sh2QTPXqMhyaAtzAr807TIyfQrmyg==", + "requires": { + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.6", + "@babel/types": "^7.23.6", + "debug": "^4.3.1", + "globals": "^11.1.0" + } + }, + "@babel/types": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.6.tgz", + "integrity": "sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==", + "requires": { + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + } + }, + "@cubejs-backend/api-gateway": { + "version": "0.34.42", + "resolved": "https://registry.npmjs.org/@cubejs-backend/api-gateway/-/api-gateway-0.34.42.tgz", + "integrity": "sha512-jj1TfsqXYQZXYdQ6yjjqfMxlC+B8C7zALunZWNy8Sy49kcZN1idA3nldOxYBLqEgZDGi0a6py+KyxCvPbI1yRQ==", + "requires": { + "@cubejs-backend/native": "^0.34.42", + "@cubejs-backend/shared": "^0.34.41", + "@ungap/structured-clone": "^0.3.4", + "body-parser": "^1.19.0", + "chrono-node": "^2.6.2", + "express-graphql": "^0.12.0", + "graphql": "^15.8.0", + "graphql-scalars": "^1.10.0", + "inflection": "^1.12.0", + "joi": "^17.8.3", + "jsonwebtoken": "^8.3.0", + "jwk-to-pem": "^2.0.4", + "moment": "^2.24.0", + "moment-timezone": "^0.5.27", + "nexus": "^1.1.0", + "node-fetch": "^2.6.1", + "ramda": "^0.27.0", + "uuid": "^8.3.2" + }, + "dependencies": { + "jsonwebtoken": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", + "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", + "requires": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^5.6.0" + } + }, + "semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==" + } + } + }, + "@cubejs-backend/base-driver": { + "version": "0.34.41", + "resolved": "https://registry.npmjs.org/@cubejs-backend/base-driver/-/base-driver-0.34.41.tgz", + "integrity": "sha512-ndAgqk92VyOgfcFoOFF3feI2qcjW2txKganmrUbjC/bnXcg4E5y8BruC8dhCD2qMJdbFOOrCFBaNVw8ZIlaHVA==", + "requires": { + "@cubejs-backend/shared": "^0.34.41", + "ramda": "^0.27.0" + } + }, + "@cubejs-backend/cloud": { + "version": "0.34.41", + "resolved": "https://registry.npmjs.org/@cubejs-backend/cloud/-/cloud-0.34.41.tgz", + "integrity": "sha512-rmWcP2nWLogyl2m2ny0uxqXUPeoH4oI1JHov6snEWenuRFac6SLJ+ElF7SL2MAp/AEbtsvGgrE2CIFLWSqYOAQ==", + "requires": { + "@cubejs-backend/dotenv": "^9.0.2", + "@cubejs-backend/shared": "^0.34.41", + "chokidar": "^3.5.1", + "env-var": "^6.3.0", + "fs-extra": "^9.1.0", + "jsonwebtoken": "^8.5.1", + "request": "^2.88.2", + "request-promise": "^4.2.5" + }, + "dependencies": { + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "jsonwebtoken": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", + "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", + "requires": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^5.6.0" + } + }, + "semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==" + }, + "universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==" + } + } + }, + "@cubejs-backend/cubesql": { + "version": "0.34.42", + "resolved": "https://registry.npmjs.org/@cubejs-backend/cubesql/-/cubesql-0.34.42.tgz", + "integrity": "sha512-6HUwteg1Dwsju/qxBIpbdYbuJyfI2jVWI3wCdsvS0PKB9b9XM8r4oQkqcaeBZFmcw2yJjgEhNWrXjBvTH2mu3A==" + }, + "@cubejs-backend/cubestore": { + "version": "0.34.41", + "resolved": "https://registry.npmjs.org/@cubejs-backend/cubestore/-/cubestore-0.34.41.tgz", + "integrity": "sha512-lseD9o3KogTcyPk5Rqv8wjoC3Yyf24/V3fOBM+wn3QR3cC+uLHIPuaszWdlgki/SAk1ZqNWCKECGypY3snBEQw==", + "requires": { + "@cubejs-backend/shared": "^0.34.41", + "@octokit/core": "^3.2.5", + "source-map-support": "^0.5.19" + } + }, + "@cubejs-backend/cubestore-driver": { + "version": "0.34.41", + "resolved": "https://registry.npmjs.org/@cubejs-backend/cubestore-driver/-/cubestore-driver-0.34.41.tgz", + "integrity": "sha512-UrMkqpwOEHJC+s99MVvkUKwzd/lX+5qTi05giYZRcwnFL18eU5epcGbYwwTbmFbZLlYs5ESJ+BfLL4fjNsp40Q==", + "requires": { + "@cubejs-backend/base-driver": "^0.34.41", + "@cubejs-backend/cubestore": "^0.34.41", + "@cubejs-backend/shared": "^0.34.41", + "csv-write-stream": "^2.0.0", + "flatbuffers": "23.3.3", + "fs-extra": "^9.1.0", + "generic-pool": "^3.6.0", + "moment-timezone": "^0.5.31", + "node-fetch": "^2.6.1", + "sqlstring": "^2.3.3", + "tempy": "^1.0.1", + "uuid": "^8.3.2", + "ws": "^7.4.3" + }, + "dependencies": { + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==" + } + } + }, + "@cubejs-backend/dotenv": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/@cubejs-backend/dotenv/-/dotenv-9.0.2.tgz", + "integrity": "sha512-yC1juhXEjM7K97KfXubDm7WGipd4Lpxe+AT8XeTRE9meRULrKlw0wtE2E8AQkGOfTBn+P1SCkePQ/BzIbOh1VA==" + }, + "@cubejs-backend/native": { + "version": "0.34.42", + "resolved": "https://registry.npmjs.org/@cubejs-backend/native/-/native-0.34.42.tgz", + "integrity": "sha512-HKU+I57wUfZVsVijURrj/jMErFAq231MymKsqvRC/WMogOR32VXRA8JNlUp04KPJoYPG68AZLoKn0TL3aQREkA==", + "requires": { + "@cubejs-backend/cubesql": "^0.34.42", + "@cubejs-backend/shared": "^0.34.41", + "@cubejs-infra/post-installer": "^0.0.7" + } + }, + "@cubejs-backend/query-orchestrator": { + "version": "0.34.41", + "resolved": "https://registry.npmjs.org/@cubejs-backend/query-orchestrator/-/query-orchestrator-0.34.41.tgz", + "integrity": "sha512-3LtXiIenuXtqGGiFILMkEl2ZqVbpPW6cc2y9O7toFFgzbxSwR+6diJrFMthvaLAAkloeMqe9sW4FWypi7CI39g==", + "requires": { + "@cubejs-backend/base-driver": "^0.34.41", + "@cubejs-backend/cubestore-driver": "^0.34.41", + "@cubejs-backend/shared": "^0.34.41", + "csv-write-stream": "^2.0.0", + "es5-ext": "0.10.53", + "generic-pool": "^3.7.1", + "ioredis": "^4.27.8", + "lru-cache": "^6.0.0", + "moment-range": "^4.0.2", + "moment-timezone": "^0.5.33", + "ramda": "^0.27.2", + "redis": "^3.0.2" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } + }, + "@cubejs-backend/schema-compiler": { + "version": "0.34.42", + "resolved": "https://registry.npmjs.org/@cubejs-backend/schema-compiler/-/schema-compiler-0.34.42.tgz", + "integrity": "sha512-+3sHT7+ZaMjBcfTPy9My0YEl4GFtVwWwfJaal9vpsdIyMcxFA5RHwDAr3nryFh0CR9JK6r4uX24JwZIvuZPzXQ==", + "requires": { + "@babel/code-frame": "^7.12.11", + "@babel/core": "^7.12.10", + "@babel/generator": "^7.12.10", + "@babel/parser": "^7.12.10", + "@babel/preset-env": "^7.12.10", + "@babel/standalone": "^7.12.10", + "@babel/traverse": "^7.12.10", + "@babel/types": "^7.12.12", + "@cubejs-backend/native": "^0.34.42", + "@cubejs-backend/shared": "^0.34.41", + "antlr4ts": "0.5.0-alpha.4", + "camelcase": "^6.2.0", + "cron-parser": "^3.5.0", + "humps": "^2.0.1", + "inflection": "^1.12.0", + "joi": "^17.8.3", + "js-yaml": "^4.1.0", + "lru-cache": "^5.1.1", + "moment-range": "^4.0.1", + "moment-timezone": "^0.5.33", + "node-dijkstra": "^2.5.0", + "ramda": "^0.27.2", + "syntax-error": "^1.3.0", + "uuid": "^8.3.2" + } + }, + "@cubejs-backend/server-core": { + "version": "0.34.42", + "resolved": "https://registry.npmjs.org/@cubejs-backend/server-core/-/server-core-0.34.42.tgz", + "integrity": "sha512-+OEKjBVzJx0JGCqxLwXSTG5RKzE6ngyQj1L029BAnkxxb/V1pl4NoOCa3vimDC8zfpLMIxeIipvt+j2L8ml3HA==", + "requires": { + "@cubejs-backend/api-gateway": "^0.34.42", + "@cubejs-backend/cloud": "^0.34.41", + "@cubejs-backend/dotenv": "^9.0.2", + "@cubejs-backend/native": "^0.34.42", + "@cubejs-backend/query-orchestrator": "^0.34.41", + "@cubejs-backend/schema-compiler": "^0.34.42", + "@cubejs-backend/shared": "^0.34.41", + "@cubejs-backend/templates": "^0.34.41", + "codesandbox-import-utils": "^2.1.12", + "cross-spawn": "^7.0.1", + "fs-extra": "^8.1.0", + "is-docker": "^2.1.1", + "joi": "^17.8.3", + "jsonwebtoken": "^8.4.0", + "lodash.clonedeep": "^4.5.0", + "lru-cache": "^5.1.1", + "moment": "^2.29.1", + "node-fetch": "^2.6.0", + "p-limit": "^3.1.0", + "promise-timeout": "^1.3.0", + "ramda": "^0.27.0", + "semver": "^6.3.0", + "serve-static": "^1.13.2", + "sqlstring": "^2.3.1", + "uuid": "^8.3.2", + "ws": "^7.5.3" + }, + "dependencies": { + "jsonwebtoken": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", + "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", + "requires": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^5.6.0" + }, + "dependencies": { + "semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==" + } + } + } + } + }, + "@cubejs-backend/shared": { + "version": "0.34.41", + "resolved": "https://registry.npmjs.org/@cubejs-backend/shared/-/shared-0.34.41.tgz", + "integrity": "sha512-WcXPhkCj+STThblbz/J4K6/lefa+L39OrD7CBwSV7CO5Fb9SsFbry7F5gyget2sopkdbwpwJd6zXHFu/03RwOg==", + "requires": { + "@oclif/color": "^0.1.2", + "bytes": "^3.1.0", + "cli-progress": "^3.9.0", + "cross-spawn": "^7.0.3", + "decompress": "^4.2.1", + "env-var": "^6.3.0", + "fs-extra": "^9.1.0", + "http-proxy-agent": "^4.0.1", + "moment-range": "^4.0.1", + "moment-timezone": "^0.5.33", + "node-fetch": "^2.6.1", + "shelljs": "^0.8.5", + "throttle-debounce": "^3.0.1", + "uuid": "^8.3.2" + }, + "dependencies": { + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==" + } + } + }, + "@cubejs-backend/templates": { + "version": "0.34.41", + "resolved": "https://registry.npmjs.org/@cubejs-backend/templates/-/templates-0.34.41.tgz", + "integrity": "sha512-NcbksDuYIG9NbBHzKZNnrmh3Ih+VXTr2SLKMmiqRMcKmFU36Z2LXNGaZl0CAexnuHJfVJq39WVZQ+maxFIPY6A==", + "requires": { + "@cubejs-backend/shared": "^0.34.41", + "cross-spawn": "^7.0.3", + "decompress": "^4.2.1", + "decompress-targz": "^4.1.1", + "fs-extra": "^9.1.0", + "node-fetch": "^2.6.1", + "ramda": "^0.27.2", + "source-map-support": "^0.5.19" + }, + "dependencies": { + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==" + } + } + }, + "@cubejs-infra/post-installer": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@cubejs-infra/post-installer/-/post-installer-0.0.7.tgz", + "integrity": "sha512-9P2cY8V0mqH+FvzVM/Z43fJmuKisln4xKjZaoQi1gLygNX0wooWzGcehibqBOkeKVMg31JBRaAQrxltIaa2rYA==", + "requires": { + "@cubejs-backend/shared": "0.33.20", + "source-map-support": "^0.5.21" + }, + "dependencies": { + "@cubejs-backend/shared": { + "version": "0.33.20", + "resolved": "https://registry.npmjs.org/@cubejs-backend/shared/-/shared-0.33.20.tgz", + "integrity": "sha512-PANWng9VLr6+55QVHQv23TyDO2o1nwEWMAXd/ujUmD7AyyCHih7UllgoHYZW18vyyQm3qPxR/J7TLOACW2OcLw==", + "requires": { + "@oclif/color": "^0.1.2", + "bytes": "^3.1.0", + "cli-progress": "^3.9.0", + "cross-spawn": "^7.0.3", + "decompress": "^4.2.1", + "env-var": "^6.3.0", + "fs-extra": "^9.1.0", + "http-proxy-agent": "^4.0.1", + "moment-range": "^4.0.1", + "moment-timezone": "^0.5.33", + "node-fetch": "^2.6.1", + "shelljs": "^0.8.5", + "throttle-debounce": "^3.0.1", + "uuid": "^8.3.2" + } + }, + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==" + } + } + }, + "@hapi/hoek": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", + "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==" + }, + "@hapi/topo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "requires": { + "@hapi/hoek": "^9.0.0" + } + }, + "@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==" + }, + "@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==" + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" + }, + "@jridgewell/trace-mapping": { + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", + "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", + "requires": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==" + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, + "@oclif/color": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@oclif/color/-/color-0.1.2.tgz", + "integrity": "sha512-M9o+DOrb8l603qvgz1FogJBUGLqcMFL1aFg2ZEL0FbXJofiNTLOWIeB4faeZTLwE6dt0xH9GpCVpzksMMzGbmA==", + "requires": { + "ansi-styles": "^3.2.1", + "chalk": "^3.0.0", + "strip-ansi": "^5.2.0", + "supports-color": "^5.4.0", + "tslib": "^1" + }, + "dependencies": { + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + } + } + }, + "@octokit/auth-token": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz", + "integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==", + "requires": { + "@octokit/types": "^6.0.3" + } + }, + "@octokit/core": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz", + "integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==", + "requires": { + "@octokit/auth-token": "^2.4.4", + "@octokit/graphql": "^4.5.8", + "@octokit/request": "^5.6.3", + "@octokit/request-error": "^2.0.5", + "@octokit/types": "^6.0.3", + "before-after-hook": "^2.2.0", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/endpoint": { + "version": "6.0.12", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", + "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", + "requires": { + "@octokit/types": "^6.0.3", + "is-plain-object": "^5.0.0", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/graphql": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz", + "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==", + "requires": { + "@octokit/request": "^5.6.0", + "@octokit/types": "^6.0.3", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/openapi-types": { + "version": "12.11.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", + "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==" + }, + "@octokit/request": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz", + "integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==", + "requires": { + "@octokit/endpoint": "^6.0.1", + "@octokit/request-error": "^2.1.0", + "@octokit/types": "^6.16.1", + "is-plain-object": "^5.0.0", + "node-fetch": "^2.6.7", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/request-error": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", + "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", + "requires": { + "@octokit/types": "^6.0.3", + "deprecation": "^2.0.0", + "once": "^1.4.0" + } + }, + "@octokit/types": { + "version": "6.41.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", + "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", + "requires": { + "@octokit/openapi-types": "^12.11.0" + } + }, + "@sideway/address": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz", + "integrity": "sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==", + "requires": { + "@hapi/hoek": "^9.0.0" + } + }, + "@sideway/formula": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", + "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==" + }, + "@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" + }, + "@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==" + }, + "@ungap/structured-clone": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-0.3.4.tgz", + "integrity": "sha512-TSVh8CpnwNAsPC5wXcIyh92Bv1gq6E9cNDeeLu7Z4h8V4/qWtXJp7y42qljRkqcpmsve1iozwv1wr+3BNdILCg==" + }, + "accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "requires": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + } + }, + "acorn-node": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", + "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", + "requires": { + "acorn": "^7.0.0", + "acorn-walk": "^7.0.0", + "xtend": "^4.0.2" + }, + "dependencies": { + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==" + } + } + }, + "acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==" + }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "requires": { + "debug": "4" + } + }, + "aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + } + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "antlr4ts": { + "version": "0.5.0-alpha.4", + "resolved": "https://registry.npmjs.org/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz", + "integrity": "sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ==" + }, + "anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==" + }, + "asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==" + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==" + }, + "aws4": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", + "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==" + }, + "babel-plugin-polyfill-corejs2": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.7.tgz", + "integrity": "sha512-LidDk/tEGDfuHW2DWh/Hgo4rmnw3cduK6ZkOI1NPFceSK3n/yAGeOsNT7FLnSGHkXj3RHGSEVkN3FsCTY6w2CQ==", + "requires": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.4.4", + "semver": "^6.3.1" + } + }, + "babel-plugin-polyfill-corejs3": { + "version": "0.8.7", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.7.tgz", + "integrity": "sha512-KyDvZYxAzkC0Aj2dAPyDzi2Ym15e5JKZSK+maI7NAwSqofvuFglbSsxE7wUOvTg9oFVnHMzVzBKcqEb4PJgtOA==", + "requires": { + "@babel/helper-define-polyfill-provider": "^0.4.4", + "core-js-compat": "^3.33.1" + } + }, + "babel-plugin-polyfill-regenerator": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.4.tgz", + "integrity": "sha512-S/x2iOCvDaCASLYsOOgWOq4bCfKYVqvO/uxjkaYyZ3rVsVE3CeAI/c84NpyuBBymEgNvHgjEot3a9/Z/kXvqsg==", + "requires": { + "@babel/helper-define-polyfill-provider": "^0.4.4" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "before-after-hook": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", + "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==" + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" + }, + "binaryextensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-2.3.0.tgz", + "integrity": "sha512-nAihlQsYGyc5Bwq6+EsubvANYGExeJKHDO3RjnvwU042fawQTQfM3Kxn7IHUXQOz4bzfwsGYYHGSvXyW4zOGLg==" + }, + "bl": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz", + "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==", + "requires": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + }, + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" + }, + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "requires": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "requires": { + "fill-range": "^7.0.1" + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==" + }, + "browserslist": { + "version": "4.22.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", + "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", + "requires": { + "caniuse-lite": "^1.0.30001565", + "electron-to-chromium": "^1.4.601", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" + } + }, + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "requires": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==" + }, + "buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, + "buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==" + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" + }, + "call-bind": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", + "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", + "requires": { + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.1", + "set-function-length": "^1.1.1" + } + }, + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==" + }, + "caniuse-lite": { + "version": "1.0.30001576", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001576.tgz", + "integrity": "sha512-ff5BdakGe2P3SQsMsiqmt1Lc8221NR1VzHj5jXN5vBny9A6fpze94HiVV/n7XRosOlsShJcvMv5mdnpjOGCEgg==" + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + } + }, + "chrono-node": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/chrono-node/-/chrono-node-2.7.4.tgz", + "integrity": "sha512-gk2xUWroQftZW3Z9mDqD3/HZW1d7fxSf0S0rNxOCfY+uUQP1FuuEcb5ulFcsEWSOQvzl02dqTeY1RK+zmc0WOQ==", + "requires": { + "dayjs": "^1.10.0" + } + }, + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==" + }, + "cli-progress": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/cli-progress/-/cli-progress-3.12.0.tgz", + "integrity": "sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==", + "requires": { + "string-width": "^4.2.3" + } + }, + "cluster-key-slot": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", + "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==" + }, + "codesandbox-import-util-types": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/codesandbox-import-util-types/-/codesandbox-import-util-types-2.2.3.tgz", + "integrity": "sha512-Qj00p60oNExthP2oR3vvXmUGjukij+rxJGuiaKM6tyUmSyimdZsqHI/TUvFFClAffk9s7hxGnQgWQ8KCce27qQ==" + }, + "codesandbox-import-utils": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/codesandbox-import-utils/-/codesandbox-import-utils-2.2.3.tgz", + "integrity": "sha512-ymtmcgZKU27U+nM2qUb21aO8Ut/u2S9s6KorOgG81weP+NA0UZkaHKlaRqbLJ9h4i/4FLvwmEXYAnTjNmp6ogg==", + "requires": { + "codesandbox-import-util-types": "^2.2.3", + "istextorbinary": "^2.2.1", + "lz-string": "^1.4.4" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==" + }, + "convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" + }, + "core-js-compat": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.35.0.tgz", + "integrity": "sha512-5blwFAddknKeNgsjBzilkdQ0+YK8L1PfqPYq40NOYMYFSS38qj+hpTcLLWwpIwA2A5bje/x5jmVn2tzUMg9IVw==", + "requires": { + "browserslist": "^4.22.2" + } + }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "cron-parser": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-3.5.0.tgz", + "integrity": "sha512-wyVZtbRs6qDfFd8ap457w3XVntdvqcwBGxBoTvJQH9KGVKL/fB+h2k3C8AqiVxvUQKN1Ps/Ns46CNViOpVDhfQ==", + "requires": { + "is-nan": "^1.3.2", + "luxon": "^1.26.0" + } + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==" + }, + "csv-write-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/csv-write-stream/-/csv-write-stream-2.0.0.tgz", + "integrity": "sha512-QTraH6FOYfM5f+YGwx71hW1nR9ZjlWri67/D4CWtiBkdce0UAa91Vc0yyHg0CjC0NeEGnvO/tBSJkA1XF9D9GQ==", + "requires": { + "argparse": "^1.0.7", + "generate-object-property": "^1.0.0", + "ndjson": "^1.3.0" + } + }, + "d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "requires": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "dayjs": { + "version": "1.11.10", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", + "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "decompress": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.1.tgz", + "integrity": "sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ==", + "requires": { + "decompress-tar": "^4.0.0", + "decompress-tarbz2": "^4.0.0", + "decompress-targz": "^4.0.0", + "decompress-unzip": "^4.0.1", + "graceful-fs": "^4.1.10", + "make-dir": "^1.0.0", + "pify": "^2.3.0", + "strip-dirs": "^2.0.0" + } + }, + "decompress-tar": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz", + "integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==", + "requires": { + "file-type": "^5.2.0", + "is-stream": "^1.1.0", + "tar-stream": "^1.5.2" + } + }, + "decompress-tarbz2": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz", + "integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==", + "requires": { + "decompress-tar": "^4.1.0", + "file-type": "^6.1.0", + "is-stream": "^1.1.0", + "seek-bzip": "^1.0.5", + "unbzip2-stream": "^1.0.9" + }, + "dependencies": { + "file-type": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-6.2.0.tgz", + "integrity": "sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==" + } + } + }, + "decompress-targz": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.1.tgz", + "integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==", + "requires": { + "decompress-tar": "^4.1.1", + "file-type": "^5.2.0", + "is-stream": "^1.1.0" + } + }, + "decompress-unzip": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz", + "integrity": "sha512-1fqeluvxgnn86MOh66u8FjbtJpAFv5wgCT9Iw8rcBqQcCo5tO8eiJw7NNTrvt9n4CRBVq7CstiS922oPgyGLrw==", + "requires": { + "file-type": "^3.8.0", + "get-stream": "^2.2.0", + "pify": "^2.3.0", + "yauzl": "^2.4.2" + }, + "dependencies": { + "file-type": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", + "integrity": "sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA==" + } + } + }, + "define-data-property": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", + "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "requires": { + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + } + }, + "define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "requires": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + } + }, + "del": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/del/-/del-6.1.1.tgz", + "integrity": "sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==", + "requires": { + "globby": "^11.0.1", + "graceful-fs": "^4.2.4", + "is-glob": "^4.0.1", + "is-path-cwd": "^2.2.0", + "is-path-inside": "^3.0.2", + "p-map": "^4.0.0", + "rimraf": "^3.0.2", + "slash": "^3.0.0" + }, + "dependencies": { + "p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "requires": { + "aggregate-error": "^3.0.0" + } + } + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" + }, + "denque": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz", + "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==" + }, + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + }, + "deprecation": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" + }, + "destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" + }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "requires": { + "path-type": "^4.0.0" + } + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "editions": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/editions/-/editions-2.3.1.tgz", + "integrity": "sha512-ptGvkwTvGdGfC0hfhKg0MT+TRLRKGtUiWGBInxOm5pz7ssADezahjCUaYuZ8Dr+C05FW0AECIIPt4WBxVINEhA==", + "requires": { + "errlop": "^2.0.0", + "semver": "^6.3.0" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "electron-to-chromium": { + "version": "1.4.623", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.623.tgz", + "integrity": "sha512-lKoz10iCYlP1WtRYdh5MvocQPWVRoI7ysp6qf18bmeBgR8abE6+I2CsfyNKztRDZvhdWc+krKT6wS7Neg8sw3A==" + }, + "elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "requires": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "env-var": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/env-var/-/env-var-6.3.0.tgz", + "integrity": "sha512-gaNzDZuVaJQJlP2SigAZLu/FieZN5MzdN7lgHNehESwlRanHwGQ/WUtJ7q//dhrj3aGBZM45yEaKOuvSJaf4mA==" + }, + "errlop": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/errlop/-/errlop-2.2.0.tgz", + "integrity": "sha512-e64Qj9+4aZzjzzFpZC7p5kmm/ccCrbLhAJplhsDXQFs87XTsXwOpH4s1Io2s90Tau/8r2j9f4l/thhDevRjzxw==" + }, + "es5-ext": { + "version": "0.10.53", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", + "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", + "requires": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.3", + "next-tick": "~1.0.0" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "requires": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" + }, + "express-graphql": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/express-graphql/-/express-graphql-0.12.0.tgz", + "integrity": "sha512-DwYaJQy0amdy3pgNtiTDuGGM2BLdj+YO2SgbKoLliCfuHv3VVTt7vNG/ZqK2hRYjtYHE2t2KB705EU94mE64zg==", + "requires": { + "accepts": "^1.3.7", + "content-type": "^1.0.4", + "http-errors": "1.8.0", + "raw-body": "^2.4.1" + }, + "dependencies": { + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==" + }, + "http-errors": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.0.tgz", + "integrity": "sha512-4I8r0C5JDhT5VkvI47QktDW75rNlGVsUf/8hzjCC/wkWI/jdTRmBb9aI7erSG82r1bjKY3F6k28WnsVxB1C73A==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==" + }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" + } + } + }, + "ext": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", + "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", + "requires": { + "type": "^2.7.2" + }, + "dependencies": { + "type": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", + "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==" + } + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==" + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "fastq": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.16.0.tgz", + "integrity": "sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA==", + "requires": { + "reusify": "^1.0.4" + } + }, + "fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "requires": { + "pend": "~1.2.0" + } + }, + "file-type": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", + "integrity": "sha512-Iq1nJ6D2+yIO4c8HHg4fyVb8mAJieo1Oloy1mLLaB2PvezNedhBVm+QU7g0qM42aiMbRXTxKKwGD17rjKNJYVQ==" + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "flatbuffers": { + "version": "23.3.3", + "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-23.3.3.tgz", + "integrity": "sha512-jmreOaAT1t55keaf+Z259Tvh8tR/Srry9K8dgCgvizhKSEr6gLGgaOJI2WFL5fkOpGOGRZwxUrlFn0GCmXUy6g==" + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==" + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "optional": true + }, + "function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" + }, + "generate-object-property": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha512-TuOwZWgJ2VAMEGJvAyPWvpqxSANF0LDpmyHauMjFYzaACvn+QTT/AZomvPCzVBV7yDN3OmwHQ5OvHaeLKre3JQ==", + "requires": { + "is-property": "^1.0.0" + } + }, + "generic-pool": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz", + "integrity": "sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==" + }, + "gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==" + }, + "get-intrinsic": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", + "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", + "requires": { + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + } + }, + "get-stream": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", + "integrity": "sha512-AUGhbbemXxrZJRD5cDvKtQxLuYaIbNtDTK8YqupCI393Q2KSTreEsLUN3ZxAWFGiKTzL6nKuzfcIvieflUX9qA==", + "requires": { + "object-assign": "^4.0.1", + "pinkie-promise": "^2.0.0" + } + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "requires": { + "is-glob": "^4.0.1" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" + }, + "globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + } + }, + "gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "requires": { + "get-intrinsic": "^1.1.3" + } + }, + "graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "graphql": { + "version": "15.8.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.8.0.tgz", + "integrity": "sha512-5gghUc24tP9HRznNpV2+FIoq3xKkj5dTQqf4v0CpdPbFVwFkWoxOM+o+2OC9ZSvjEMTjfmG9QT+gcvggTwW1zw==" + }, + "graphql-scalars": { + "version": "1.22.4", + "resolved": "https://registry.npmjs.org/graphql-scalars/-/graphql-scalars-1.22.4.tgz", + "integrity": "sha512-ILnv7jq5VKHLUyoaTFX7lgYrjCd6vTee9i8/B+D4zJKJT5TguOl0KkpPEbXHjmeor8AZYrVsrYUHdqRBMX1pjA==", + "requires": { + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + } + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==" + }, + "har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "requires": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" + }, + "has-property-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", + "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "requires": { + "get-intrinsic": "^1.2.2" + } + }, + "has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==" + }, + "has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" + }, + "hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "requires": { + "function-bind": "^1.1.2" + } + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "requires": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + } + }, + "http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "requires": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "humps": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/humps/-/humps-2.0.1.tgz", + "integrity": "sha512-E0eIbrFWUhwfXJmsbdjRQFQPrl5pTEoKlz163j1mTqqUnU9PgR4AgB8AIITzuB3vLBdxZXyZ9TDIrwB2OASz4g==" + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + }, + "ignore": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", + "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==" + }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==" + }, + "inflection": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.4.tgz", + "integrity": "sha512-6I/HUDeYFfuNCVS3td055BaXBwKYuzw7K3ExVMStBowKo9oOAMJIXIHvdyR3iboTCp1b+1i5DSkIZTcwIktuDw==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==" + }, + "ioredis": { + "version": "4.28.5", + "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-4.28.5.tgz", + "integrity": "sha512-3GYo0GJtLqgNXj4YhrisLaNNvWSNwSS2wS4OELGfGxH8I69+XfNdnmV1AyN+ZqMh0i7eX+SWjrwFKDBDgfBC1A==", + "requires": { + "cluster-key-slot": "^1.1.0", + "debug": "^4.3.1", + "denque": "^1.1.0", + "lodash.defaults": "^4.2.0", + "lodash.flatten": "^4.4.0", + "lodash.isarguments": "^3.1.0", + "p-map": "^2.1.0", + "redis-commands": "1.7.0", + "redis-errors": "^1.2.0", + "redis-parser": "^3.0.0", + "standard-as-callback": "^2.1.0" + } + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "requires": { + "hasown": "^2.0.0" + } + }, + "is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==" + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-nan": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", + "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + } + }, + "is-natural-number": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", + "integrity": "sha512-Y4LTamMe0DDQIIAlaer9eKebAlDSV6huy+TWhJVPlzZh2o4tRP5SQWFlLn5N0To4mDD22/qdOq+veo1cSISLgQ==" + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + }, + "is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==" + }, + "is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==" + }, + "is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==" + }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==" + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==" + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" + }, + "istextorbinary": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-2.6.0.tgz", + "integrity": "sha512-+XRlFseT8B3L9KyjxxLjfXSLMuErKDsd8DBNrsaxoViABMEZlOSCstwmw0qpoFX3+U6yWU1yhLudAe6/lETGGA==", + "requires": { + "binaryextensions": "^2.1.2", + "editions": "^2.2.0", + "textextensions": "^2.5.0" + } + }, + "iterall": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/iterall/-/iterall-1.3.0.tgz", + "integrity": "sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg==" + }, + "joi": { + "version": "17.11.0", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.11.0.tgz", + "integrity": "sha512-NgB+lZLNoqISVy1rZocE9PZI36bL/77ie924Ri43yEvi9GUUMPeyVIr8KdFTMUlby1p0PBYMk9spIxEUQYqrJQ==", + "requires": { + "@hapi/hoek": "^9.0.0", + "@hapi/topo": "^5.0.0", + "@sideway/address": "^4.1.3", + "@sideway/formula": "^3.0.1", + "@sideway/pinpoint": "^2.0.0" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "requires": { + "argparse": "^2.0.1" + }, + "dependencies": { + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + } + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==" + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" + }, + "json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" + }, + "json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==" + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsprim": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", + "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + } + }, + "jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "jwk-to-pem": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/jwk-to-pem/-/jwk-to-pem-2.0.5.tgz", + "integrity": "sha512-L90jwellhO8jRKYwbssU9ifaMVqajzj3fpRjDKcsDzrslU9syRbFqfkXtT4B89HYAap+xsxNcxgBSB09ig+a7A==", + "requires": { + "asn1.js": "^5.3.0", + "elliptic": "^6.5.4", + "safe-buffer": "^5.0.1" + } + }, + "jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "requires": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==" + }, + "lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" + }, + "lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==" + }, + "lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==" + }, + "lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==" + }, + "lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, + "lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "requires": { + "yallist": "^3.0.2" + } + }, + "luxon": { + "version": "1.28.1", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-1.28.1.tgz", + "integrity": "sha512-gYHAa180mKrNIUJCbwpmD0aTu9kV0dREDrwNnuyFAsO1Wt0EVYSZelPnJlbj9HplzXX/YWXHFTL45kvZ53M0pw==" + }, + "lz-string": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==" + }, + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "requires": { + "pify": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==" + } + } + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==" + }, + "micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "requires": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + } + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==" + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, + "moment": { + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==" + }, + "moment-range": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/moment-range/-/moment-range-4.0.2.tgz", + "integrity": "sha512-n8sceWwSTjmz++nFHzeNEUsYtDqjgXgcOBzsHi+BoXQU2FW+eU92LUaK8gqOiSu5PG57Q9sYj1Fz4LRDj4FtKA==", + "requires": { + "es6-symbol": "^3.1.0" + } + }, + "moment-timezone": { + "version": "0.5.44", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.44.tgz", + "integrity": "sha512-nv3YpzI/8lkQn0U6RkLd+f0W/zy/JnoR5/EyPz/dNkPTBjA2jNLCVxaiQ8QpeLymhSZvX0wCL5s27NQWdOPwAw==", + "requires": { + "moment": "^2.29.4" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "ndjson": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/ndjson/-/ndjson-1.5.0.tgz", + "integrity": "sha512-hUPLuaziboGjNF7wHngkgVc0FOclR8dDk/HfEvTtDr/iUrqBWiRcRSTK3/nLOqKH33th714BrMmTPtObI9gZxQ==", + "requires": { + "json-stringify-safe": "^5.0.1", + "minimist": "^1.2.0", + "split2": "^2.1.0", + "through2": "^2.0.3" + } + }, + "negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" + }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha512-mc/caHeUcdjnC/boPWJefDr4KUIWQNv+tlnFnJd38QMou86QtxQzBJfxgGRzvx8jazYRqrVlaHarfO72uNxPOg==" + }, + "nexus": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/nexus/-/nexus-1.3.0.tgz", + "integrity": "sha512-w/s19OiNOs0LrtP7pBmD9/FqJHvZLmCipVRt6v1PM8cRUYIbhEswyNKGHVoC4eHZGPSnD+bOf5A3+gnbt0A5/A==", + "requires": { + "iterall": "^1.3.0", + "tslib": "^2.0.3" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + } + } + }, + "node-dijkstra": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/node-dijkstra/-/node-dijkstra-2.5.0.tgz", + "integrity": "sha512-2REYb1lo8yDRAY1gsdhjwQdGVSh47VI5Z5wS8sCqydO/P1OVAKOwLuV1fDxNLvbrtMspW7k2UZ2JKIKP06hl+A==" + }, + "node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "requires": { + "whatwg-url": "^5.0.0" + } + }, + "node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, + "object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==" + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + }, + "on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "requires": { + "ee-first": "1.1.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "requires": { + "wrappy": "1" + } + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==" + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" + }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==" + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" + }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==" + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==" + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", + "requires": { + "pinkie": "^2.0.0" + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "promise-timeout": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/promise-timeout/-/promise-timeout-1.3.0.tgz", + "integrity": "sha512-5yANTE0tmi5++POym6OgtFmwfDvOXABD9oj/jLQr5GPEyuNEb7jH4wbbANJceJid49jwhi1RddxnhnEAb/doqg==" + }, + "psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" + }, + "punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==" + }, + "qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "requires": { + "side-channel": "^1.0.4" + } + }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==" + }, + "ramda": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.27.2.tgz", + "integrity": "sha512-SbiLPU40JuJniHexQSAgad32hfwd+DRUdwF2PlVuI5RZD0/vahUco7R8vD86J/tcEKKF9vZrUVwgtmGCqlCKyA==" + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + }, + "raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "requires": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, + "readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "requires": { + "picomatch": "^2.2.1" + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", + "requires": { + "resolve": "^1.1.6" + } + }, + "redis": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/redis/-/redis-3.1.2.tgz", + "integrity": "sha512-grn5KoZLr/qrRQVwoSkmzdbw6pwF+/rwODtrOr6vuBRiR/f3rjSTGupbF90Zpqm2oenix8Do6RV7pYEkGwlKkw==", + "requires": { + "denque": "^1.5.0", + "redis-commands": "^1.7.0", + "redis-errors": "^1.2.0", + "redis-parser": "^3.0.0" + } + }, + "redis-commands": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.7.0.tgz", + "integrity": "sha512-nJWqw3bTFy21hX/CPKHth6sfhZbdiHP6bTawSgQBlKOVRG7EZkfHbbHwQJnrE4vsQf0CMNE+3gJ4Fmm16vdVlQ==" + }, + "redis-errors": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", + "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==" + }, + "redis-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", + "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", + "requires": { + "redis-errors": "^1.0.0" + } + }, + "regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" + }, + "regenerate-unicode-properties": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", + "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", + "requires": { + "regenerate": "^1.4.2" + } + }, + "regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + }, + "regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "requires": { + "@babel/runtime": "^7.8.4" + } + }, + "regexpu-core": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", + "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "requires": { + "@babel/regjsgen": "^0.8.0", + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.1.0", + "regjsparser": "^0.9.1", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + } + }, + "regjsparser": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "requires": { + "jsesc": "~0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==" + } + } + }, + "request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "dependencies": { + "qs": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", + "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==" + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" + } + } + }, + "request-promise": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.6.tgz", + "integrity": "sha512-HCHI3DJJUakkOr8fNoCc73E5nU5bqITjOYFMDrKHYOXWXrgD/SBaC7LjwuPymUprRyuF06UK7hd/lMHkmUXglQ==", + "requires": { + "bluebird": "^3.5.0", + "request-promise-core": "1.1.4", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" + } + }, + "request-promise-core": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz", + "integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==", + "requires": { + "lodash": "^4.17.19" + } + }, + "resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "requires": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "requires": { + "glob": "^7.1.3" + } + }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "requires": { + "queue-microtask": "^1.2.2" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "seek-bzip": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.6.tgz", + "integrity": "sha512-e1QtP3YL5tWww8uKaOCQ18UxIT2laNBXHjV/S2WYCiK4udiv8lkG89KRIoCjUagnAmCBurjF4zEVX2ByBbnCjQ==", + "requires": { + "commander": "^2.8.1" + } + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + }, + "send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "requires": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + } + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + } + }, + "set-function-length": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", + "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "requires": { + "define-data-property": "^1.1.1", + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + } + }, + "setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" + }, + "shelljs": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", + "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", + "requires": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + } + }, + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "split2": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-2.2.0.tgz", + "integrity": "sha512-RAb22TG39LhI31MbreBgIuKiIKhVsawfTgEGqKHTK87aG+ul/PB8Sqoi3I7kVdRWiCfrKxK3uo4/YUkpNvhPbw==", + "requires": { + "through2": "^2.0.2" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + }, + "sqlstring": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", + "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==" + }, + "sshpk": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", + "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "standard-as-callback": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", + "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==" + }, + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" + }, + "stealthy-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha512-ZnWpYnYugiOVEY5GkcuJK1io5V8QmNYChG62gSit9pQVGErXtrKuPC55ITaVSukmMta5qpMU7vqLt2Lnni4f/g==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + } + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "strip-dirs": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz", + "integrity": "sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==", + "requires": { + "is-natural-number": "^4.0.1" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" + }, + "syntax-error": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.4.0.tgz", + "integrity": "sha512-YPPlu67mdnHGTup2A8ff7BC2Pjq0e0Yp/IyTFN03zWO0RcK07uLcbi7C2KpGR2FvWbaB0+bfE27a+sBKebSo7w==", + "requires": { + "acorn-node": "^1.2.0" + } + }, + "tar-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", + "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", + "requires": { + "bl": "^1.0.0", + "buffer-alloc": "^1.2.0", + "end-of-stream": "^1.0.0", + "fs-constants": "^1.0.0", + "readable-stream": "^2.3.0", + "to-buffer": "^1.1.1", + "xtend": "^4.0.0" + } + }, + "temp-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", + "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==" + }, + "tempy": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tempy/-/tempy-1.0.1.tgz", + "integrity": "sha512-biM9brNqxSc04Ee71hzFbryD11nX7VPhQQY32AdDmjFvodsRFz/3ufeoTZ6uYkRFfGo188tENcASNs3vTdsM0w==", + "requires": { + "del": "^6.0.0", + "is-stream": "^2.0.0", + "temp-dir": "^2.0.0", + "type-fest": "^0.16.0", + "unique-string": "^2.0.0" + }, + "dependencies": { + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" + } + } + }, + "textextensions": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-2.6.0.tgz", + "integrity": "sha512-49WtAWS+tcsy93dRt6P0P3AMD2m5PvXRhuEA0kaXos5ZLlujtYmpmFsB+QvWUSxE1ZsstmYXfQ7L40+EcQgpAQ==" + }, + "throttle-debounce": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-3.0.1.tgz", + "integrity": "sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg==" + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "to-buffer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==" + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==" + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "requires": { + "is-number": "^7.0.0" + } + }, + "toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" + }, + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" + }, + "type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" + }, + "type-fest": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", + "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==" + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "unbzip2-stream": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", + "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", + "requires": { + "buffer": "^5.2.1", + "through": "^2.3.8" + } + }, + "unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==" + }, + "unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "requires": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + } + }, + "unicode-match-property-value-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", + "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==" + }, + "unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==" + }, + "unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "requires": { + "crypto-random-string": "^2.0.0" + } + }, + "universal-user-agent": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz", + "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==" + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" + }, + "update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "requires": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + } + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "requires": { + "punycode": "^2.1.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + }, + "dependencies": { + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" + } + } + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "requires": { + "isexe": "^2.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "requires": {} + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "requires": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==" + } + } +} diff --git a/services/libs/cubejs/src/app/package.json b/services/libs/cubejs/src/app/package.json new file mode 100644 index 0000000000..8a99a67d3e --- /dev/null +++ b/services/libs/cubejs/src/app/package.json @@ -0,0 +1,24 @@ +{ + "name": "@crowd/cubejs-app", + "version": "1.0.0", + "private": true, + "scripts": { + "lint": "./node_modules/.bin/eslint --ext .ts src --max-warnings=0", + "format": "./node_modules/.bin/prettier --write \"src/**/*.ts\"", + "format-check": "./node_modules/.bin/prettier --check .", + "tsc-check": "./node_modules/.bin/tsc --noEmit" + }, + "dependencies": { + "@cubejs-backend/server-core": "^0.34.34" + }, + "devDependencies": { + "@types/node": "^18.16.3", + "@typescript-eslint/eslint-plugin": "^5.59.2", + "@typescript-eslint/parser": "^5.59.2", + "eslint": "^8.39.0", + "eslint-config-prettier": "^8.8.0", + "eslint-plugin-prettier": "^4.2.1", + "prettier": "^2.8.8", + "typescript": "^5.0.4" + } +} diff --git a/services/libs/cubejs/src/schema/Activities.js b/services/libs/cubejs/src/app/schema/Activities.js similarity index 88% rename from services/libs/cubejs/src/schema/Activities.js rename to services/libs/cubejs/src/app/schema/Activities.js index e7e0758adb..1f6234acd1 100644 --- a/services/libs/cubejs/src/schema/Activities.js +++ b/services/libs/cubejs/src/app/schema/Activities.js @@ -15,6 +15,13 @@ cube('Activities', { }, }, + joins: { + Segments: { + sql: `${CUBE}."segmentId" = ${Segments}."id"`, + relationship: 'belongsTo', + }, + }, + dimensions: { id: { sql: `${CUBE}.id`, diff --git a/services/libs/cubejs/src/schema/Conversations.js b/services/libs/cubejs/src/app/schema/Conversations.js similarity index 100% rename from services/libs/cubejs/src/schema/Conversations.js rename to services/libs/cubejs/src/app/schema/Conversations.js diff --git a/services/libs/cubejs/src/app/schema/MemberIdentities.js b/services/libs/cubejs/src/app/schema/MemberIdentities.js new file mode 100644 index 0000000000..cb07514734 --- /dev/null +++ b/services/libs/cubejs/src/app/schema/MemberIdentities.js @@ -0,0 +1,25 @@ +cube('MemberIdentities', { + sql_table: '"memberIdentities"', + + preAggregations: {}, + + joins: { + Members: { + sql: `${CUBE}."memberId" = ${Members}.id`, + relationship: 'belongsTo', + }, + }, + + measures: {}, + + dimensions: { + platform: { + sql: `${CUBE}.platform`, + type: 'string', + }, + username: { + sql: `${CUBE}.username`, + type: 'string', + }, + }, +}) diff --git a/services/libs/cubejs/src/schema/MemberOrganizations.js b/services/libs/cubejs/src/app/schema/MemberOrganizations.js similarity index 100% rename from services/libs/cubejs/src/schema/MemberOrganizations.js rename to services/libs/cubejs/src/app/schema/MemberOrganizations.js diff --git a/services/libs/cubejs/src/schema/MemberSegments.js b/services/libs/cubejs/src/app/schema/MemberSegments.js similarity index 100% rename from services/libs/cubejs/src/schema/MemberSegments.js rename to services/libs/cubejs/src/app/schema/MemberSegments.js diff --git a/services/libs/cubejs/src/schema/MemberTags.js b/services/libs/cubejs/src/app/schema/MemberTags.js similarity index 100% rename from services/libs/cubejs/src/schema/MemberTags.js rename to services/libs/cubejs/src/app/schema/MemberTags.js diff --git a/services/libs/cubejs/src/schema/Members.js b/services/libs/cubejs/src/app/schema/Members.js similarity index 69% rename from services/libs/cubejs/src/schema/Members.js rename to services/libs/cubejs/src/app/schema/Members.js index d79531dbf5..f0b2c5c580 100644 --- a/services/libs/cubejs/src/schema/Members.js +++ b/services/libs/cubejs/src/app/schema/Members.js @@ -21,6 +21,11 @@ cube('Members', { sql: `${CUBE}.id = ${MemberSegments}."memberId"`, relationship: 'belongsTo', }, + + MemberIdentities: { + sql: `${CUBE}.id = ${MemberIdentities}."memberId"`, + relationship: 'hasMany', + }, }, measures: { @@ -82,5 +87,19 @@ cube('Members', { sql: `${CUBE}."score"`, type: 'number', }, + + engagementLevel: { + type: 'string', + case: { + when: [ + { sql: `${CUBE}.score = 0 or ${CUBE}.score = 1`, label: `Silent` }, + { sql: `${CUBE}.score = 2 or ${CUBE}.score = 3`, label: `Quiet` }, + { sql: `${CUBE}.score = 4 or ${CUBE}.score = 5 or ${CUBE}.score = 6`, label: `Engaged` }, + { sql: `${CUBE}.score = 7 or ${CUBE}.score = 8`, label: `Fan` }, + { sql: `${CUBE}.score = 9 or ${CUBE}.score = 10`, label: `Ultra` }, + ], + else: { label: `Unknown` }, + }, + }, }, }) diff --git a/services/libs/cubejs/src/app/schema/OrganizationIdentities.js b/services/libs/cubejs/src/app/schema/OrganizationIdentities.js new file mode 100644 index 0000000000..bea03cf151 --- /dev/null +++ b/services/libs/cubejs/src/app/schema/OrganizationIdentities.js @@ -0,0 +1,25 @@ +cube('OrganizationIdentities', { + sql_table: '"organizationIdentities"', + + preAggregations: {}, + + joins: { + Organizations: { + sql: `${CUBE}."organizationId" = ${Organizations}.id`, + relationship: 'belongsTo', + }, + }, + + measures: {}, + + dimensions: { + platform: { + sql: `${CUBE}.platform`, + type: 'string', + }, + name: { + sql: `${CUBE}.name`, + type: 'string', + }, + }, +}) diff --git a/services/libs/cubejs/src/schema/OrganizationSegments.js b/services/libs/cubejs/src/app/schema/OrganizationSegments.js similarity index 100% rename from services/libs/cubejs/src/schema/OrganizationSegments.js rename to services/libs/cubejs/src/app/schema/OrganizationSegments.js diff --git a/services/libs/cubejs/src/schema/Organizations.js b/services/libs/cubejs/src/app/schema/Organizations.js similarity index 76% rename from services/libs/cubejs/src/schema/Organizations.js rename to services/libs/cubejs/src/app/schema/Organizations.js index 3562a59715..13faabf2ef 100644 --- a/services/libs/cubejs/src/schema/Organizations.js +++ b/services/libs/cubejs/src/app/schema/Organizations.js @@ -5,10 +5,19 @@ cube('Organizations', { sql: `${CUBE}.id = ${MemberOrganizations}."organizationId"`, relationship: 'hasMany', }, + Activities: { + sql: `${CUBE}.id = ${Activities}."organizationId"`, + relationship: 'hasMany', + }, OrganizationSegments: { sql: `${CUBE}.id = ${OrganizationSegments}."organizationId"`, relationship: 'belongsTo', }, + + OrganizationIdentities: { + sql: `${CUBE}.id = ${OrganizationIdentities}."organizationId"`, + relationship: 'hasMany', + }, }, measures: { count: { diff --git a/services/libs/cubejs/src/schema/Segments.js b/services/libs/cubejs/src/app/schema/Segments.js similarity index 100% rename from services/libs/cubejs/src/schema/Segments.js rename to services/libs/cubejs/src/app/schema/Segments.js diff --git a/services/libs/cubejs/src/schema/Sentiment.js b/services/libs/cubejs/src/app/schema/Sentiment.js similarity index 100% rename from services/libs/cubejs/src/schema/Sentiment.js rename to services/libs/cubejs/src/app/schema/Sentiment.js diff --git a/services/libs/cubejs/src/schema/Tags.js b/services/libs/cubejs/src/app/schema/Tags.js similarity index 100% rename from services/libs/cubejs/src/schema/Tags.js rename to services/libs/cubejs/src/app/schema/Tags.js diff --git a/services/libs/cubejs/src/dimensions.ts b/services/libs/cubejs/src/dimensions.ts deleted file mode 100644 index 6e22154560..0000000000 --- a/services/libs/cubejs/src/dimensions.ts +++ /dev/null @@ -1,13 +0,0 @@ -export default class CubeDimensions { - static readonly MEMBER_JOINED_AT: string = 'Members.joinedAt' - - static readonly IS_TEAM_MEMBER: string = 'Members.isTeamMember' - - static readonly ACTIVITY_DATE: string = 'Activities.date' - - static readonly CONVERSATION_CREATED_AT: string = 'Conversations.createdat' - - static readonly CONVERSATION_FIRST_ACTIVITY_TIME: string = 'Conversations.firstActivityTime' - - static readonly ORGANIZATIONS_JOINED_AT: string = 'Organizations.joinedAt' -} diff --git a/services/libs/cubejs/src/enums.ts b/services/libs/cubejs/src/enums.ts new file mode 100644 index 0000000000..e6d7e51f28 --- /dev/null +++ b/services/libs/cubejs/src/enums.ts @@ -0,0 +1,42 @@ +export enum CubeDimension { + MEMBER_JOINED_AT = 'Members.joinedAt', + MEMBER_JOINED_AT_DAY = 'Members.joinedAt.day', + IS_TEAM_MEMBER = 'Members.isTeamMember', + IS_BOT = 'Members.isBot', + IS_ORGANIZATION = 'Members.isOrganization', + ACTIVITY_DATE = 'Activities.date', + ACTIVITY_DATE_DAY = 'Activities.date.day', + ACTIVITY_PLATFORM = 'Activities.platform', + MEMBER_IDENTITIES_PLATFORM = 'MemberIdentities.platform', + ACTIVITY_TYPE = 'Activities.type', + ACTIVITY_SENTIMENT_MOOD = 'Activities.sentimentMood', + CONVERSATION_CREATED_AT = 'Conversations.createdat', + CONVERSATION_FIRST_ACTIVITY_TIME = 'Conversations.firstActivityTime', + ORGANIZATIONS_JOINED_AT = 'Organizations.joinedAt', + ORGANIZATIONS_JOINED_AT_DAY = 'Organizations.joinedAt.day', + ORGANIZATION_IDENTITIES_PLATFORM = 'OrganizationIdentities.platform', + SEGMENTS_ID = 'Segments.id', +} + +export enum CubeMeasure { + MEMBER_COUNT = 'Members.count', + ACTIVITY_COUNT = 'Activities.count', + CONVERSATION_COUNT = 'Conversations.count', + ORGANIZATION_COUNT = 'Organizations.count', +} + +export enum CubeGranularity { + SECOND = 'second', + MINUTE = 'minute', + HOUR = 'hour', + DAY = 'day', + WEEK = 'week', + MONTH = 'month', + QUARTER = 'quarter', + YEAR = 'year', +} + +export enum CubeOrderDirection { + ASC = 'asc', + DESC = 'desc', +} diff --git a/services/libs/cubejs/src/index.ts b/services/libs/cubejs/src/index.ts index 58d4913299..0660f03960 100644 --- a/services/libs/cubejs/src/index.ts +++ b/services/libs/cubejs/src/index.ts @@ -1,7 +1,5 @@ -export * from './cube' -export * from './dimensions' -export * from './measures' +export * from './types' +export * from './enums' export * from './repository' export * from './service' - export * from './metrics' diff --git a/services/libs/cubejs/src/measures.ts b/services/libs/cubejs/src/measures.ts deleted file mode 100644 index 3ba595f54d..0000000000 --- a/services/libs/cubejs/src/measures.ts +++ /dev/null @@ -1,9 +0,0 @@ -export default class CubeMeasures { - static readonly MEMBER_COUNT: string = 'Members.count' - - static readonly ACTIVITY_COUNT: string = 'Activities.count' - - static readonly CONVERSATION_COUNT: string = 'Conversations.count' - - static readonly ORGANIZATION_COUNT: string = 'Organizations.count' -} diff --git a/services/libs/cubejs/src/metrics/activeMembers.ts b/services/libs/cubejs/src/metrics/activeMembers.ts index 08059418bc..999f2fe04d 100644 --- a/services/libs/cubejs/src/metrics/activeMembers.ts +++ b/services/libs/cubejs/src/metrics/activeMembers.ts @@ -1,10 +1,11 @@ import moment from 'moment' import { CubeJsService } from '../service' -import CubeDimensions from '../dimensions' -import CubeMeasures from '../measures' +import { CubeGranularity, CubeDimension, CubeMeasure, CubeOrderDirection } from '../enums' +import { ICubeFilter, ICubeOrder, IDashboardFilter } from '../types' + +/**import CubeDimension from '../dimensions' -/** * Gets `active members` count for a given date range. * Members are active when they have an activity in given date range. * @param cjs cubejs service instance @@ -12,28 +13,70 @@ import CubeMeasures from '../measures' * @param endDate * @returns */ -export default async (cjs: CubeJsService, startDate: moment.Moment, endDate: moment.Moment) => { - const activeMembers = - ( - await cjs.load({ - measures: [CubeMeasures.MEMBER_COUNT], - timeDimensions: [ - { - dimension: CubeDimensions.ACTIVITY_DATE, - dateRange: [startDate.format('YYYY-MM-DD'), endDate.format('YYYY-MM-DD')], - }, - ], - limit: 1, - order: { [CubeDimensions.MEMBER_JOINED_AT]: 'asc' }, - filters: [ - { - member: CubeDimensions.IS_TEAM_MEMBER, - operator: 'equals', - values: ['false'], - }, - ], - }) - )[0][CubeMeasures.MEMBER_COUNT] ?? 0 - - return parseInt(activeMembers, 10) +export default async ( + cjs: CubeJsService, + startDate: moment.Moment, + endDate: moment.Moment, + granularity: CubeGranularity | string = null, + filter: IDashboardFilter = {}, + order: ICubeOrder = { [CubeDimension.MEMBER_JOINED_AT]: CubeOrderDirection.ASC }, + rawResult = false, +) => { + const filters: ICubeFilter[] = [ + { + member: CubeDimension.IS_TEAM_MEMBER, + operator: 'equals', + values: ['false'], + }, + { + member: CubeDimension.IS_BOT, + operator: 'equals', + values: ['false'], + }, + { + member: CubeDimension.IS_ORGANIZATION, + operator: 'equals', + values: ['false'], + }, + ] + + if (filter.platform) { + filters.push({ + member: CubeDimension.ACTIVITY_PLATFORM, + operator: 'equals', + values: [filter.platform], + }) + } + + if (filter.segments) { + filters.push({ + member: CubeDimension.SEGMENTS_ID, + operator: 'equals', + values: filter.segments, + }) + } + + const activeMembers = await cjs.load( + { + measures: [CubeMeasure.MEMBER_COUNT], + timeDimensions: [ + { + dimension: CubeDimension.ACTIVITY_DATE, + dateRange: [startDate.format('YYYY-MM-DD'), endDate.format('YYYY-MM-DD')], + granularity, + }, + ], + order, + filters, + }, + rawResult, + ) + + if (rawResult || granularity) { + return activeMembers + } + + const parsedResult = activeMembers[0][CubeMeasure.MEMBER_COUNT] ?? 0 + + return parseInt(parsedResult, 10) } diff --git a/services/libs/cubejs/src/metrics/activeOrganizations.ts b/services/libs/cubejs/src/metrics/activeOrganizations.ts index c7c198087c..cf31eb04de 100644 --- a/services/libs/cubejs/src/metrics/activeOrganizations.ts +++ b/services/libs/cubejs/src/metrics/activeOrganizations.ts @@ -1,8 +1,8 @@ import moment from 'moment' import { CubeJsService } from '../service' -import CubeDimensions from '../dimensions' -import CubeMeasures from '../measures' +import { CubeGranularity, CubeDimension, CubeMeasure, CubeOrderDirection } from '../enums' +import { ICubeFilter, ICubeOrder, IDashboardFilter } from '../types' /** * Gets `active organizations` count for a given date range. @@ -12,28 +12,69 @@ import CubeMeasures from '../measures' * @param endDate * @returns */ -export default async (cjs: CubeJsService, startDate: moment.Moment, endDate: moment.Moment) => { - const activeOrganizations = - ( - await cjs.load({ - measures: [CubeMeasures.ORGANIZATION_COUNT], - timeDimensions: [ - { - dimension: CubeDimensions.ACTIVITY_DATE, - dateRange: [startDate.format('YYYY-MM-DD'), endDate.format('YYYY-MM-DD')], - }, - ], - limit: 1, - order: { [CubeDimensions.ORGANIZATIONS_JOINED_AT]: 'asc' }, - filters: [ - { - member: CubeDimensions.IS_TEAM_MEMBER, - operator: 'equals', - values: ['false'], - }, - ], - }) - )[0][CubeMeasures.ORGANIZATION_COUNT] ?? 0 - - return parseInt(activeOrganizations, 10) +export default async ( + cjs: CubeJsService, + startDate: moment.Moment, + endDate: moment.Moment, + granularity: CubeGranularity | string = undefined, + filter: IDashboardFilter = {}, + order: ICubeOrder = { [CubeDimension.ORGANIZATIONS_JOINED_AT]: CubeOrderDirection.ASC }, + rawResult = false, +) => { + /* + const filters: ICubeFilter[] = [ + { + member: CubeDimension.IS_TEAM_MEMBER, + operator: 'equals', + values: ['false'], + }, + { + member: CubeDimension.IS_BOT, + operator: 'equals', + values: ['false'], + }, + ] + */ + + const filters: ICubeFilter[] = [] + + if (filter.platform) { + filters.push({ + member: CubeDimension.ACTIVITY_PLATFORM, + operator: 'equals', + values: [filter.platform], + }) + } + + if (filter.segments) { + filters.push({ + member: CubeDimension.SEGMENTS_ID, + operator: 'equals', + values: filter.segments, + }) + } + + const activeOrganizations = await cjs.load( + { + measures: [CubeMeasure.ORGANIZATION_COUNT], + timeDimensions: [ + { + dimension: CubeDimension.ACTIVITY_DATE, + dateRange: [startDate.format('YYYY-MM-DD'), endDate.format('YYYY-MM-DD')], + granularity, + }, + ], + order, + filters, + }, + rawResult, + ) + + if (rawResult || granularity) { + return activeOrganizations + } + + const parsedResult = activeOrganizations[0][CubeMeasure.ORGANIZATION_COUNT] ?? 0 + + return parseInt(parsedResult, 10) } diff --git a/services/libs/cubejs/src/metrics/newActivities.ts b/services/libs/cubejs/src/metrics/newActivities.ts index f040e7df03..6ee5cbd621 100644 --- a/services/libs/cubejs/src/metrics/newActivities.ts +++ b/services/libs/cubejs/src/metrics/newActivities.ts @@ -1,8 +1,8 @@ import moment from 'moment' import { CubeJsService } from '../service' -import CubeDimensions from '../dimensions' -import CubeMeasures from '../measures' +import { CubeGranularity, CubeOrderDirection, CubeDimension, CubeMeasure } from '../enums' +import { ICubeFilter, ICubeOrder, IDashboardFilter } from '../types' /** * Gets `new activities` count for a given date range. @@ -12,28 +12,67 @@ import CubeMeasures from '../measures' * @param endDate * @returns */ -export default async (cjs: CubeJsService, startDate: moment.Moment, endDate: moment.Moment) => { - const newActivities = - ( - await cjs.load({ - measures: [CubeMeasures.ACTIVITY_COUNT], - timeDimensions: [ - { - dimension: CubeDimensions.ACTIVITY_DATE, - dateRange: [startDate.format('YYYY-MM-DD'), endDate.format('YYYY-MM-DD')], - }, - ], - limit: 1, - order: { [CubeDimensions.ACTIVITY_DATE]: 'asc' }, - filters: [ - { - member: CubeDimensions.IS_TEAM_MEMBER, - operator: 'equals', - values: ['false'], - }, - ], - }) - )[0][CubeMeasures.ACTIVITY_COUNT] ?? 0 - - return parseInt(newActivities, 10) +export default async ( + cjs: CubeJsService, + startDate: moment.Moment, + endDate: moment.Moment, + granularity: CubeGranularity | string = null, + dimensions: CubeDimension[] | string[] = [], + filter: IDashboardFilter = {}, + order: ICubeOrder = { [CubeDimension.ACTIVITY_DATE]: CubeOrderDirection.ASC }, + rawResult = false, +) => { + const filters: ICubeFilter[] = [ + { + member: CubeDimension.IS_TEAM_MEMBER, + operator: 'equals', + values: ['false'], + }, + { + member: CubeDimension.IS_BOT, + operator: 'equals', + values: ['false'], + }, + ] + + if (filter.platform) { + filters.push({ + member: CubeDimension.ACTIVITY_PLATFORM, + operator: 'equals', + values: [filter.platform], + }) + } + + if (filter.segments) { + filters.push({ + member: CubeDimension.SEGMENTS_ID, + operator: 'equals', + values: filter.segments, + }) + } + + const newActivities = await cjs.load( + { + measures: [CubeMeasure.ACTIVITY_COUNT], + dimensions, + timeDimensions: [ + { + dimension: CubeDimension.ACTIVITY_DATE, + dateRange: [startDate.format('YYYY-MM-DD'), endDate.format('YYYY-MM-DD')], + granularity, + }, + ], + order, + filters, + }, + rawResult, + ) + + if (rawResult || granularity) { + return newActivities + } + + const parsedResult = newActivities[0][CubeMeasure.ACTIVITY_COUNT] ?? 0 + + return parseInt(parsedResult, 10) } diff --git a/services/libs/cubejs/src/metrics/newConversations.ts b/services/libs/cubejs/src/metrics/newConversations.ts index fa9b49ec95..00fb3d1f17 100644 --- a/services/libs/cubejs/src/metrics/newConversations.ts +++ b/services/libs/cubejs/src/metrics/newConversations.ts @@ -1,8 +1,7 @@ import moment from 'moment' import { CubeJsService } from '../service' -import CubeDimensions from '../dimensions' -import CubeMeasures from '../measures' +import { CubeDimension, CubeMeasure } from '../enums' /** * Gets `new conversations` count for a given date range. @@ -16,16 +15,16 @@ export default async (cjs: CubeJsService, startDate: moment.Moment, endDate: mom const newConversations = ( await cjs.load({ - measures: [CubeMeasures.CONVERSATION_COUNT], + measures: [CubeMeasure.CONVERSATION_COUNT], timeDimensions: [ { - dimension: CubeDimensions.CONVERSATION_FIRST_ACTIVITY_TIME, + dimension: CubeDimension.CONVERSATION_FIRST_ACTIVITY_TIME, dateRange: [startDate.format('YYYY-MM-DD'), endDate.format('YYYY-MM-DD')], }, ], limit: 1, }) - )[0][CubeMeasures.CONVERSATION_COUNT] ?? 0 + )[0][CubeMeasure.CONVERSATION_COUNT] ?? 0 return parseInt(newConversations, 10) } diff --git a/services/libs/cubejs/src/metrics/newMembers.ts b/services/libs/cubejs/src/metrics/newMembers.ts index c2ad159269..5e84ace465 100644 --- a/services/libs/cubejs/src/metrics/newMembers.ts +++ b/services/libs/cubejs/src/metrics/newMembers.ts @@ -1,39 +1,79 @@ import moment from 'moment' import { CubeJsService } from '../service' -import CubeDimensions from '../dimensions' -import CubeMeasures from '../measures' +import { CubeGranularity, CubeDimension, CubeMeasure, CubeOrderDirection } from '../enums' +import { ICubeFilter, ICubeOrder, IDashboardFilter } from '../types' /** - * Gets `new members` count for a given date range. + * Gets `new members` count or timeseries data for a given date range and granularity. * Members are new when member.joinedAt is in between given date range. * @param cjs cubejs service instance * @param startDate * @param endDate * @returns */ -export default async (cjs: CubeJsService, startDate: moment.Moment, endDate: moment.Moment) => { - const newMembers = - ( - await cjs.load({ - measures: [CubeMeasures.MEMBER_COUNT], - timeDimensions: [ - { - dimension: CubeDimensions.MEMBER_JOINED_AT, - dateRange: [startDate.format('YYYY-MM-DD'), endDate.format('YYYY-MM-DD')], - }, - ], - limit: 1, - order: { [CubeDimensions.MEMBER_JOINED_AT]: 'asc' }, - filters: [ - { - member: CubeDimensions.IS_TEAM_MEMBER, - operator: 'equals', - values: ['false'], - }, - ], - }) - )[0][CubeMeasures.MEMBER_COUNT] ?? 0 - - return parseInt(newMembers, 10) +export default async ( + cjs: CubeJsService, + startDate: moment.Moment, + endDate: moment.Moment, + granularity: CubeGranularity | string = null, + filter: IDashboardFilter = {}, + order: ICubeOrder = { [CubeDimension.MEMBER_JOINED_AT]: CubeOrderDirection.ASC }, + rawResult = false, +) => { + const filters: ICubeFilter[] = [ + { + member: CubeDimension.IS_TEAM_MEMBER, + operator: 'equals', + values: ['false'], + }, + { + member: CubeDimension.IS_BOT, + operator: 'equals', + values: ['false'], + }, + { + member: CubeDimension.IS_ORGANIZATION, + operator: 'equals', + values: ['false'], + }, + ] + + if (filter.platform) { + filters.push({ + member: CubeDimension.MEMBER_IDENTITIES_PLATFORM, + operator: 'equals', + values: [filter.platform], + }) + } + + if (filter.segments) { + filters.push({ + member: CubeDimension.SEGMENTS_ID, + operator: 'equals', + values: filter.segments, + }) + } + + const query = { + measures: [CubeMeasure.MEMBER_COUNT], + timeDimensions: [ + { + dimension: CubeDimension.MEMBER_JOINED_AT, + dateRange: [startDate.format('YYYY-MM-DD'), endDate.format('YYYY-MM-DD')], + granularity, + }, + ], + order, + filters, + } + + const newMembers = await cjs.load(query, rawResult) + + if (rawResult || granularity) { + return newMembers + } + const parsedResult = newMembers[0][CubeMeasure.MEMBER_COUNT] ?? 0 + + return parseInt(parsedResult, 10) } diff --git a/services/libs/cubejs/src/metrics/newOrganizations.ts b/services/libs/cubejs/src/metrics/newOrganizations.ts index b7a2323584..139a338ec0 100644 --- a/services/libs/cubejs/src/metrics/newOrganizations.ts +++ b/services/libs/cubejs/src/metrics/newOrganizations.ts @@ -1,8 +1,8 @@ import moment from 'moment' import { CubeJsService } from '../service' -import CubeDimensions from '../dimensions' -import CubeMeasures from '../measures' +import { CubeGranularity, CubeDimension, CubeMeasure, CubeOrderDirection } from '../enums' +import { ICubeFilter, ICubeOrder, IDashboardFilter } from '../types' /** * Gets `new organizations` count for a given date range. @@ -12,28 +12,65 @@ import CubeMeasures from '../measures' * @param endDate * @returns */ -export default async (cjs: CubeJsService, startDate: moment.Moment, endDate: moment.Moment) => { - const newOrganizations = - ( - await cjs.load({ - measures: [CubeMeasures.ORGANIZATION_COUNT], - timeDimensions: [ - { - dimension: CubeDimensions.ORGANIZATIONS_JOINED_AT, - dateRange: [startDate.format('YYYY-MM-DD'), endDate.format('YYYY-MM-DD')], - }, - ], - limit: 1, - order: { [CubeDimensions.ORGANIZATIONS_JOINED_AT]: 'asc' }, - filters: [ - { - member: CubeDimensions.IS_TEAM_MEMBER, - operator: 'equals', - values: ['false'], - }, - ], - }) - )[0][CubeMeasures.ORGANIZATION_COUNT] ?? 0 - - return parseInt(newOrganizations, 10) +export default async ( + cjs: CubeJsService, + startDate: moment.Moment, + endDate: moment.Moment, + granularity: CubeGranularity | string = null, + filter: IDashboardFilter = {}, + order: ICubeOrder = { [CubeDimension.ORGANIZATIONS_JOINED_AT]: CubeOrderDirection.ASC }, + rawResult = false, +) => { + const filters: ICubeFilter[] = [ + { + member: CubeDimension.IS_TEAM_MEMBER, + operator: 'equals', + values: ['false'], + }, + { + member: CubeDimension.IS_BOT, + operator: 'equals', + values: ['false'], + }, + ] + + if (filter.platform) { + filters.push({ + member: CubeDimension.ORGANIZATION_IDENTITIES_PLATFORM, + operator: 'equals', + values: [filter.platform], + }) + } + + if (filter.segments) { + filters.push({ + member: CubeDimension.SEGMENTS_ID, + operator: 'equals', + values: filter.segments, + }) + } + + const newOrganizations = await cjs.load( + { + measures: [CubeMeasure.ORGANIZATION_COUNT], + timeDimensions: [ + { + dimension: CubeDimension.ORGANIZATIONS_JOINED_AT, + dateRange: [startDate.format('YYYY-MM-DD'), endDate.format('YYYY-MM-DD')], + granularity, + }, + ], + order, + filters, + }, + rawResult, + ) + + if (rawResult || granularity) { + return newOrganizations + } + + const parsedResult = newOrganizations[0][CubeMeasure.ORGANIZATION_COUNT] ?? 0 + + return parseInt(parsedResult, 10) } diff --git a/services/libs/cubejs/src/service.ts b/services/libs/cubejs/src/service.ts index 0c2d95d9a8..8b2fa5267b 100644 --- a/services/libs/cubejs/src/service.ts +++ b/services/libs/cubejs/src/service.ts @@ -1,6 +1,7 @@ import jwt, { JsonWebTokenError } from 'jsonwebtoken' import cubejs from '@cubejs-client/core' import { Error400 } from '@crowd/common' +import { Logger } from '@crowd/logging' export class CubeJsService { private tenantId: string @@ -15,13 +16,16 @@ export class CubeJsService { // eslint-disable-next-line @typescript-eslint/no-explicit-any meta: any + log: Logger + /** * Sets tenant security context for cubejs api. * Also initializes cubejs api object from security context. * @param tenantId * @param segments */ - async init(tenantId: string, segments: string[]): Promise { + async init(tenantId: string, segments: string[], log?: Logger): Promise { + this.log = log this.tenantId = tenantId this.segments = segments this.token = await CubeJsService.generateJwtToken(this.tenantId, this.segments) @@ -34,8 +38,11 @@ export class CubeJsService { * @returns */ // eslint-disable-next-line @typescript-eslint/no-explicit-any - async load(query: any): Promise { + async load(query: any, rawResult = false): Promise { const result = await this.api.load(query) + if (rawResult) { + return result.loadResponse + } return result.loadResponses[0].data } diff --git a/services/libs/cubejs/src/types.ts b/services/libs/cubejs/src/types.ts new file mode 100644 index 0000000000..33facb45cb --- /dev/null +++ b/services/libs/cubejs/src/types.ts @@ -0,0 +1,16 @@ +import { CubeDimension, CubeOrderDirection, CubeMeasure } from './enums' + +export interface ICubeFilter { + member: CubeDimension + operator: string + values: string[] +} + +export interface IDashboardFilter { + platform?: string + segments?: string[] +} + +type CubeOrderKey = CubeDimension | CubeMeasure + +export type ICubeOrder = { [key in CubeOrderKey]?: CubeOrderDirection | string } diff --git a/services/libs/database/src/utility.ts b/services/libs/database/src/utility.ts index a8c1fefdcc..12a3a278e1 100644 --- a/services/libs/database/src/utility.ts +++ b/services/libs/database/src/utility.ts @@ -1,5 +1,6 @@ import { isNullOrUndefined } from '@crowd/common' import { ITableName } from './types' +import pgp from 'pg-promise' export const escapeTableName = (tableName: ITableName): string => { return `${ @@ -14,3 +15,9 @@ export const arePrimitivesDbEqual = (a: unknown, b: unknown): boolean => { return a === b } + +export const eqOrNull = (value: string) => ({ + rawType: true, + toPostgres: () => + pgp.as.format(`${value === null || value === undefined ? 'IS NULL' : '= $1'}`, value), +}) diff --git a/services/libs/feature-flags/src/index.ts b/services/libs/feature-flags/src/index.ts index fc3ec6b1f7..22a074b0e6 100644 --- a/services/libs/feature-flags/src/index.ts +++ b/services/libs/feature-flags/src/index.ts @@ -57,7 +57,7 @@ export const getUnleashClient = async (cfg: IUnleashConfig): Promise Promise, + contextLoader: UnleashContextLoader, client?: Unleash, redis?: RedisClient, redisTimeoutSeconds?: number, @@ -95,3 +95,6 @@ export const isFeatureEnabled = async ( } export * from 'unleash-client' + +export type UnleashClient = Unleash +export type UnleashContextLoader = () => Promise diff --git a/services/libs/integrations/src/integrations/activityTypes.ts b/services/libs/integrations/src/integrations/activityTypes.ts index 3a0efcfe09..3db7e068e4 100644 --- a/services/libs/integrations/src/integrations/activityTypes.ts +++ b/services/libs/integrations/src/integrations/activityTypes.ts @@ -1,5 +1,6 @@ import { ActivityTypeDisplayProperties, DefaultActivityTypes, PlatformType } from '@crowd/types' import { DevToActivityType } from './devto/types' +import { YoutubeActivityType } from './youtube/types' import { GithubActivityType } from './github/types' import { LinkedinActivityType } from './premium/linkedin/types' import { StackOverflowActivityType } from './stackoverflow/types' @@ -12,6 +13,7 @@ import { isUrl } from '@crowd/common' import { DiscordActivityType } from './discord/types' import { GITHUB_GRID } from './github/grid' import { DEVTO_GRID } from './devto/grid' +import { Youtube_GRID } from './youtube/grid' import { DISCORD_GRID } from './discord/grid' import { HACKERNEWS_GRID } from './hackernews/grid' import { LINKEDIN_GRID } from './premium/linkedin/grid' @@ -480,6 +482,18 @@ export const DEFAULT_ACTIVITY_TYPE_SETTINGS: DefaultActivityTypes = { isContribution: true, }, }, + [PlatformType.YOUTUBE]: { + [YoutubeActivityType.COMMENT]: { + display: { + default: + 'commented on {attributes.videoTitle}', + short: 'commented', + channel: + '{attributes.videoTitle}', + }, + isContribution: Youtube_GRID[YoutubeActivityType.COMMENT].isContribution, + }, + }, [PlatformType.DEVTO]: { [DevToActivityType.COMMENT]: { display: { diff --git a/services/libs/integrations/src/integrations/discord/api/getMember.ts b/services/libs/integrations/src/integrations/discord/api/getMember.ts index 7af5705ab3..a33cbb7a2e 100644 --- a/services/libs/integrations/src/integrations/discord/api/getMember.ts +++ b/services/libs/integrations/src/integrations/discord/api/getMember.ts @@ -10,6 +10,17 @@ export const getMember = async ( token: string, ctx: IProcessStreamContext, ): Promise => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + if (typeof guildId !== 'string' || guildId.trim() === '') { + throw new Error('Invalid guildId') + } + if (typeof userId !== 'string' || userId.trim() === '') { + throw new Error('Invalid userId') + } + if (typeof token !== 'string' || token.trim() === '') { + throw new Error('Invalid token') + } + // eslint-disable-next-line @typescript-eslint/no-explicit-any const config: AxiosRequestConfig = { method: 'get', diff --git a/services/libs/integrations/src/integrations/discord/index.ts b/services/libs/integrations/src/integrations/discord/index.ts index 7ff7911ab5..c3b3285ae5 100644 --- a/services/libs/integrations/src/integrations/discord/index.ts +++ b/services/libs/integrations/src/integrations/discord/index.ts @@ -9,6 +9,7 @@ import processWebhookStream from './processWebhookStream' const descriptor: IIntegrationDescriptor = { type: PlatformType.DISCORD, memberAttributes: DISCORD_MEMBER_ATTRIBUTES, + checkEvery: 3 * 60, // 3 hours generateStreams, processStream, processData, diff --git a/services/libs/integrations/src/integrations/github/api/graphql/baseQuery.ts b/services/libs/integrations/src/integrations/github/api/graphql/baseQuery.ts index 8e3cb6ae48..f879d634e7 100644 --- a/services/libs/integrations/src/integrations/github/api/graphql/baseQuery.ts +++ b/services/libs/integrations/src/integrations/github/api/graphql/baseQuery.ts @@ -35,6 +35,7 @@ class BaseQuery { }` static ORGANIZATION_SELECT = `{ + login email url location diff --git a/services/libs/integrations/src/integrations/github/api/graphql/forks.ts b/services/libs/integrations/src/integrations/github/api/graphql/forks.ts index 44928fb20d..804f81ee13 100644 --- a/services/libs/integrations/src/integrations/github/api/graphql/forks.ts +++ b/services/libs/integrations/src/integrations/github/api/graphql/forks.ts @@ -12,12 +12,26 @@ class ForksQuery extends BaseQuery { pageInfo ${BaseQuery.PAGE_SELECT} nodes { owner { - ... on User ${BaseQuery.USER_SELECT} + __typename + ... on Organization ${BaseQuery.ORGANIZATION_SELECT} + ... on User ${BaseQuery.USER_SELECT} } name url id createdAt + indirectForks: forks(last: 100) { + nodes { + owner { + __typename + ... on Organization ${BaseQuery.ORGANIZATION_SELECT} + ... on User ${BaseQuery.USER_SELECT} + } + id + url + createdAt + } + } } } } diff --git a/services/libs/integrations/src/integrations/github/generateStreams.ts b/services/libs/integrations/src/integrations/github/generateStreams.ts index 017bbc4a32..b37b649f7a 100644 --- a/services/libs/integrations/src/integrations/github/generateStreams.ts +++ b/services/libs/integrations/src/integrations/github/generateStreams.ts @@ -29,22 +29,23 @@ const handler: GenerateStreamsHandler = async (ctx) => { } if (manualSettings.repos) { - const repo = manualSettings.repos[0] // TODO: support multiple repos - for (const endpoint of [ - GithubStreamType.STARGAZERS, - GithubStreamType.FORKS, - GithubStreamType.PULLS, - GithubStreamType.ISSUES, - GithubStreamType.DISCUSSIONS, - ]) { - if ( - manualSettings.streamType === GithubManualStreamType.ALL || - manualSettings.streamType === streamToManualStreamMap.get(endpoint) - ) { - await ctx.publishStream(`${endpoint}:${repo.name}:firstPage`, { - repo, - page: '', - }) + for (const repo of manualSettings.repos) { + for (const endpoint of [ + GithubStreamType.STARGAZERS, + GithubStreamType.FORKS, + GithubStreamType.PULLS, + GithubStreamType.ISSUES, + GithubStreamType.DISCUSSIONS, + ]) { + if ( + manualSettings.streamType === GithubManualStreamType.ALL || + manualSettings.streamType === streamToManualStreamMap.get(endpoint) + ) { + await ctx.publishStream(`${endpoint}:${repo.name}:firstPage`, { + repo, + page: '', + }) + } } } } diff --git a/services/libs/integrations/src/integrations/github/processData.ts b/services/libs/integrations/src/integrations/github/processData.ts index 9f60d9a728..5a3e0a2055 100644 --- a/services/libs/integrations/src/integrations/github/processData.ts +++ b/services/libs/integrations/src/integrations/github/processData.ts @@ -7,12 +7,14 @@ import { GithubWebhookData, GithubActivityType, GithubPrepareMemberOutput, + GithubPrepareOrgMemberOutput, GithubActivitySubType, GithubWehookEvent, GithubPullRequest, GithubIssue, GithubPullRequestTimelineItem, GithubIssueTimelineItem, + INDIRECT_FORK, } from './types' import { IActivityData, @@ -136,6 +138,56 @@ const parseMember = (memberData: GithubPrepareMemberOutput): IMemberData => { return member } +const parseOrgMember = (memberData: GithubPrepareOrgMemberOutput): IMemberData => { + const { orgFromApi } = memberData + + const member: IMemberData = { + identities: [ + { + platform: PlatformType.GITHUB, + username: orgFromApi.login, + }, + ], + ...(orgFromApi?.twitterUsername && { + weakIdentities: [ + { + platform: PlatformType.TWITTER, + username: orgFromApi.twitterUsername, + }, + ], + }), + displayName: orgFromApi?.name?.trim() || orgFromApi.login, + attributes: { + [MemberAttributeName.URL]: { + [PlatformType.GITHUB]: orgFromApi.url, + }, + [MemberAttributeName.BIO]: { + [PlatformType.GITHUB]: orgFromApi.description || '', + }, + [MemberAttributeName.LOCATION]: { + [PlatformType.GITHUB]: orgFromApi.location || '', + }, + [MemberAttributeName.AVATAR_URL]: { + [PlatformType.GITHUB]: orgFromApi.avatarUrl || '', + }, + }, + emails: orgFromApi.email ? [orgFromApi.email] : [], + } + + if (orgFromApi.websiteUrl) { + member.attributes[MemberAttributeName.WEBSITE_URL] = { + [PlatformType.GITHUB]: orgFromApi.websiteUrl, + } + } + + // mark as organization + member.attributes[MemberAttributeName.IS_ORGANIZATION] = { + [PlatformType.GITHUB]: true, + } + + return member +} + const parseStar: ProcessDataHandler = async (ctx) => { const apiData = ctx.data as GithubApiData const data = apiData.data @@ -164,11 +216,87 @@ const parseStar: ProcessDataHandler = async (ctx) => { const parseFork: ProcessDataHandler = async (ctx) => { const apiData = ctx.data as GithubApiData + + if (apiData.orgMember && !apiData.member) { + await parseForkByOrg(ctx) + return + } else if (apiData.member && apiData.orgMember) { + throw new Error('Both member and orgMember are present') + } else if (!apiData.member && !apiData.orgMember) { + throw new Error('Both member and orgMember are missing') + } + const data = apiData.data + const relatedData = apiData.relatedData const memberData = apiData.member + const subType = apiData.subType const member = parseMember(memberData) + if (subType && subType === INDIRECT_FORK) { + const activity: IActivityData = { + type: GithubActivityType.FORK, + sourceId: data.id, + sourceParentId: '', + timestamp: new Date(data.createdAt).toISOString(), + channel: apiData.repo.url, + member, + score: GITHUB_GRID.fork.score, + isContribution: GITHUB_GRID.fork.isContribution, + attributes: { + isIndirectFork: true, + directParent: relatedData.url, + }, + } + + await ctx.publishActivity(activity) + return + } + + const activity: IActivityData = { + type: GithubActivityType.FORK, + sourceId: data.id, + sourceParentId: '', + timestamp: new Date(data.createdAt).toISOString(), + channel: apiData.repo.url, + member, + score: GITHUB_GRID.fork.score, + isContribution: GITHUB_GRID.fork.isContribution, + } + + await ctx.publishActivity(activity) +} + +const parseForkByOrg: ProcessDataHandler = async (ctx) => { + const apiData = ctx.data as GithubApiData + const data = apiData.data + const relatedData = apiData.relatedData + const memberData = apiData.orgMember + const subType = apiData.subType + + const member = parseOrgMember(memberData) + + if (subType && subType === INDIRECT_FORK) { + const activity: IActivityData = { + type: GithubActivityType.FORK, + sourceId: data.id, + sourceParentId: '', + timestamp: new Date(data.createdAt).toISOString(), + channel: apiData.repo.url, + member, + score: GITHUB_GRID.fork.score, + isContribution: GITHUB_GRID.fork.isContribution, + attributes: { + isIndirectFork: true, + directParent: relatedData.url, + isForkByOrg: true, + }, + } + + await ctx.publishActivity(activity) + return + } + const activity: IActivityData = { type: GithubActivityType.FORK, sourceId: data.id, @@ -178,6 +306,9 @@ const parseFork: ProcessDataHandler = async (ctx) => { member, score: GITHUB_GRID.fork.score, isContribution: GITHUB_GRID.fork.isContribution, + attributes: { + isForkByOrg: true, + }, } await ctx.publishActivity(activity) diff --git a/services/libs/integrations/src/integrations/github/processStream.ts b/services/libs/integrations/src/integrations/github/processStream.ts index 65f3444c9a..8537353f90 100644 --- a/services/libs/integrations/src/integrations/github/processStream.ts +++ b/services/libs/integrations/src/integrations/github/processStream.ts @@ -33,11 +33,13 @@ import { GithubIntegrationSettings, GithubPlatformSettings, GithubPrepareMemberOutput, + GithubPrepareOrgMemberOutput, GithubPullRequestEvents, GithubRootStream, GithubStreamType, Repo, Repos, + INDIRECT_FORK, } from './types' import { GithubTokenRotator } from './tokenRotator' @@ -224,6 +226,12 @@ export const prepareMember = async ( } } +export const prepareMemberFromOrg = (orgFromApi: any): GithubPrepareOrgMemberOutput => { + return { + orgFromApi, + } +} + /** * Searches given repository name among installed repositories * Returns null if given repo is not found. @@ -355,15 +363,60 @@ const processForksStream: ProcessStreamHandler = async (ctx) => { await publishNextPageStream(ctx, result) for (const record of result.data) { - const member = await prepareMember(record.owner, ctx) + if (record.owner.__typename === 'User') { + const member = await prepareMember(record.owner, ctx) - // publish data - await ctx.publishData({ - type: GithubActivityType.FORK, - data: record, - member, - repo: data.repo, - }) + // publish data + await ctx.publishData({ + type: GithubActivityType.FORK, + data: record, + member, + repo: data.repo, + }) + } else if (record.owner.__typename === 'Organization') { + const orgMember = prepareMemberFromOrg(record.owner) + + // publish data + await ctx.publishData({ + type: GithubActivityType.FORK, + data: record, + orgMember, + repo: data.repo, + }) + } else { + ctx.log.warn(`Unsupported owner type: ${record.owner.__typename}`) + } + + // traverse through indirect forks + for (const indirectFork of record.indirectForks.nodes) { + if (indirectFork.owner.__typename === 'User') { + const member = await prepareMember(indirectFork.owner, ctx) + + // publish data + await ctx.publishData({ + type: GithubActivityType.FORK, + subType: INDIRECT_FORK, + data: indirectFork, + relatedData: record, + member, + repo: data.repo, + }) + } else if (indirectFork.owner.__typename === 'Organization') { + const orgMember = prepareMemberFromOrg(indirectFork.owner) + + // publish data + await ctx.publishData({ + type: GithubActivityType.FORK, + subType: INDIRECT_FORK, + data: indirectFork, + relatedData: record, + orgMember, + repo: data.repo, + }) + } else { + ctx.log.warn(`Unsupported owner type: ${indirectFork.owner.__typename}`) + } + } } } diff --git a/services/libs/integrations/src/integrations/github/types.ts b/services/libs/integrations/src/integrations/github/types.ts index a1425dd835..340acd7d05 100644 --- a/services/libs/integrations/src/integrations/github/types.ts +++ b/services/libs/integrations/src/integrations/github/types.ts @@ -119,12 +119,15 @@ export enum GithubManualStreamType { DISCUSSIONS = 'discussions', } +export const INDIRECT_FORK = 'indirect-fork' + export interface GithubApiData { type: GithubActivityType subType?: string data: any[] | any relatedData?: any | any[] - member: GithubPrepareMemberOutput + member?: GithubPrepareMemberOutput + orgMember?: GithubPrepareOrgMemberOutput objectMember?: GithubPrepareMemberOutput sourceParentId?: string repo: Repo @@ -216,3 +219,7 @@ export interface GithubPrepareMemberOutput { orgs: any memberFromApi: any } + +export interface GithubPrepareOrgMemberOutput { + orgFromApi: any +} diff --git a/services/libs/integrations/src/integrations/groupsio/processStream.ts b/services/libs/integrations/src/integrations/groupsio/processStream.ts index 7a3f0b548f..d0065071d3 100644 --- a/services/libs/integrations/src/integrations/groupsio/processStream.ts +++ b/services/libs/integrations/src/integrations/groupsio/processStream.ts @@ -115,7 +115,7 @@ const processTopicStream: ProcessStreamHandler = async (ctx) => { // we need to create a fake member object member = { user_id: userId, - full_name: message.name || 'Anonymous User', + full_name: 'Anonymous User', email: 'anonymous+fake+email@groups.io', group_id: message.group_id, } as MemberInfoMinimal diff --git a/services/libs/integrations/src/integrations/memberAttributes.ts b/services/libs/integrations/src/integrations/memberAttributes.ts index 446008ed5c..cd315eecb5 100644 --- a/services/libs/integrations/src/integrations/memberAttributes.ts +++ b/services/libs/integrations/src/integrations/memberAttributes.ts @@ -65,4 +65,11 @@ export const DEFAULT_MEMBER_ATTRIBUTES: IMemberAttribute[] = [ canDelete: false, show: false, }, + { + name: MemberAttributes[MemberAttributeName.IS_DELETED].name, + label: MemberAttributes[MemberAttributeName.IS_DELETED].label, + type: MemberAttributeType.BOOLEAN, + canDelete: false, + show: false, + }, ] diff --git a/services/libs/integrations/src/integrations/premium/hubspot/api/batchCreateMembers.ts b/services/libs/integrations/src/integrations/premium/hubspot/api/batchCreateMembers.ts index b7a9364020..a6b621e5a8 100644 --- a/services/libs/integrations/src/integrations/premium/hubspot/api/batchCreateMembers.ts +++ b/services/libs/integrations/src/integrations/premium/hubspot/api/batchCreateMembers.ts @@ -5,8 +5,7 @@ import { getNangoToken } from './../../../nango' import { IMember, PlatformType } from '@crowd/types' import { RequestThrottler } from '@crowd/common' import { HubspotMemberFieldMapper } from '../field-mapper/memberFieldMapper' -import { IBatchCreateMembersResult } from './types' -import { batchUpdateMembers } from './batchUpdateMembers' +import { IBatchCreateMemberResultWithConflicts } from './types' import { getContactById } from './contactById' export const batchCreateMembers = async ( @@ -15,7 +14,8 @@ export const batchCreateMembers = async ( memberMapper: HubspotMemberFieldMapper, ctx: IProcessStreamContext | IGenerateStreamsContext, throttler: RequestThrottler, -): Promise => { + conflicts: IMember[] = [], +): Promise => { const config: AxiosRequestConfig = { method: 'post', url: `https://api.hubapi.com/crm/v3/objects/contacts/batch/create`, @@ -95,23 +95,27 @@ export const batchCreateMembers = async ( const result = await throttler.throttle(() => axios(config)) // return hubspot ids back to sync worker for saving - return result.data.results.reduce((acc, m) => { + const membersCreated = result.data.results.reduce((acc, m) => { const member = members.find( (crowdMember) => - crowdMember.emails.length > 0 && crowdMember.emails[0] === m.properties.email, + crowdMember.emails.length > 0 && crowdMember.emails.includes(m.properties.email), ) - const hubspotPayload = hubspotMembers.find( - (hubspotMember) => hubspotMember.properties.email === m.properties.email, - ) + if (member) { + const hubspotPayload = hubspotMembers.find( + (hubspotMember) => hubspotMember.properties.email === m.properties.email, + ) + + acc.push({ + memberId: member.id, + sourceId: m.id, + lastSyncedPayload: hubspotPayload, + }) + } - acc.push({ - memberId: member.id, - sourceId: m.id, - lastSyncedPayload: hubspotPayload, - }) return acc }, []) + return { members: membersCreated, conflicts } } catch (err) { // this means that member actually exists in hubspot but we tried re-creating it // handle it gracefully @@ -150,8 +154,14 @@ export const batchCreateMembers = async ( return m }) - await batchUpdateMembers(nangoId, updateMembers, memberMapper, ctx, throttler) - return await batchCreateMembers(nangoId, createMembers, memberMapper, ctx, throttler) + return await batchCreateMembers( + nangoId, + createMembers, + memberMapper, + ctx, + throttler, + conflicts.concat(updateMembers), + ) } } } else { diff --git a/services/libs/integrations/src/integrations/premium/hubspot/api/types.ts b/services/libs/integrations/src/integrations/premium/hubspot/api/types.ts index 26f69af3dd..76450201b4 100644 --- a/services/libs/integrations/src/integrations/premium/hubspot/api/types.ts +++ b/services/libs/integrations/src/integrations/premium/hubspot/api/types.ts @@ -1,3 +1,5 @@ +import { IMember } from '@crowd/types' + export interface IPaginatedResponse { elements: T[] after?: string @@ -17,7 +19,16 @@ export interface IBatchCreateMembersResult { lastSyncedPayload: unknown } -export type IBatchUpdateMembersResult = IBatchCreateMembersResult +export interface IBatchCreateMemberResultWithConflicts { + members: IBatchCreateMembersResult[] + conflicts: IMember[] +} + +export interface IBatchUpdateMembersResult { + memberId: string + sourceId: string + lastSyncedPayload: unknown +} export interface IBatchOperationResult { created: IBatchCreateMembersResult[] | IBatchCreateOrganizationsResult[] diff --git a/services/libs/integrations/src/integrations/premium/hubspot/field-mapper/memberFieldMapper.ts b/services/libs/integrations/src/integrations/premium/hubspot/field-mapper/memberFieldMapper.ts index 44e58a93ef..c67a912a6f 100644 --- a/services/libs/integrations/src/integrations/premium/hubspot/field-mapper/memberFieldMapper.ts +++ b/services/libs/integrations/src/integrations/premium/hubspot/field-mapper/memberFieldMapper.ts @@ -45,6 +45,12 @@ export class HubspotMemberFieldMapper extends HubspotFieldMapper { reach: { hubspotType: HubspotPropertyType.NUMBER, readonly: true, + serialize: (reach) => { + if (reach?.total) { + return reach.total + } + return 0 + }, }, numberOfOpensourceContributions: { hubspotType: HubspotPropertyType.NUMBER, @@ -198,7 +204,7 @@ export class HubspotMemberFieldMapper extends HubspotFieldMapper { const identityPlatform = crowdKey.split('.')[1] || null if (identityPlatform) { - member.identities.push({ + member.weakIdentities.push({ username: contactProperties[hubspotPropertyName], platform: identityPlatform, }) diff --git a/services/libs/integrations/src/integrations/premium/hubspot/processStream.ts b/services/libs/integrations/src/integrations/premium/hubspot/processStream.ts index da0f13b92f..989fc97598 100644 --- a/services/libs/integrations/src/integrations/premium/hubspot/processStream.ts +++ b/services/libs/integrations/src/integrations/premium/hubspot/processStream.ts @@ -15,7 +15,7 @@ import { getAllCompanies } from './api/companies' import { RequestThrottler } from '@crowd/common' const processRootStream: ProcessStreamHandler = async (ctx) => { - const throttler = new RequestThrottler(99, 11000, ctx.log) + const throttler = new RequestThrottler(90, 15000, ctx.log) const settings = ctx.integration.settings as IHubspotIntegrationSettings diff --git a/services/libs/integrations/src/integrations/premium/hubspot/processSyncRemote.ts b/services/libs/integrations/src/integrations/premium/hubspot/processSyncRemote.ts index 7a8b5dafac..703686845d 100644 --- a/services/libs/integrations/src/integrations/premium/hubspot/processSyncRemote.ts +++ b/services/libs/integrations/src/integrations/premium/hubspot/processSyncRemote.ts @@ -60,13 +60,27 @@ const handler: ProcessIntegrationSyncHandler = async ( ) if (toCreate.length > 0) { - membersCreatedInHubspot = await batchCreateMembers( + const batchCreateResult = await batchCreateMembers( nangoId, toCreate as IMember[], memberMapper, integrationContext, throttler, ) + membersCreatedInHubspot = batchCreateResult.members + if (batchCreateResult.conflicts.length > 0) { + // append create conflicts to update array + // also remove duplicates (where two members have same email, we should select one of them to sync) + ;(toUpdate as IMember[]) = (toUpdate as IMember[]) + .concat(batchCreateResult.conflicts) + .filter( + (member, index, self) => + index === + self.findIndex( + (m) => m.attributes?.sourceId?.hubspot === member.attributes?.sourceId?.hubspot, + ), + ) + } } if (toUpdate.length > 0) { diff --git a/services/libs/integrations/src/integrations/prettyActivityTypes.ts b/services/libs/integrations/src/integrations/prettyActivityTypes.ts index bd6599912e..ed3bd97118 100644 --- a/services/libs/integrations/src/integrations/prettyActivityTypes.ts +++ b/services/libs/integrations/src/integrations/prettyActivityTypes.ts @@ -54,6 +54,9 @@ export const prettyActivityTypes = { [PlatformType.DEVTO]: { comment: 'comment', }, + [PlatformType.YOUTUBE]: { + comment: 'comment', + }, [PlatformType.HACKERNEWS]: { [HackerNewsActivityType.POST]: 'posted', [HackerNewsActivityType.COMMENT]: 'commented ', diff --git a/services/libs/integrations/src/integrations/reddit/processData.ts b/services/libs/integrations/src/integrations/reddit/processData.ts index 986a88aeab..b8ab7d7898 100644 --- a/services/libs/integrations/src/integrations/reddit/processData.ts +++ b/services/libs/integrations/src/integrations/reddit/processData.ts @@ -124,6 +124,11 @@ function parseMember(activity: RedditPost | RedditComment): IMemberData { }, ], displayName: 'Deleted User', + attributes: { + [MemberAttributeName.IS_DELETED]: { + [PlatformType.REDDIT]: true, + }, + }, } } return { diff --git a/services/libs/integrations/src/integrations/twitter/api/getPostsByMention.ts b/services/libs/integrations/src/integrations/twitter/api/getPostsByMention.ts index c5a5f03cb5..8d7784cea1 100644 --- a/services/libs/integrations/src/integrations/twitter/api/getPostsByMention.ts +++ b/services/libs/integrations/src/integrations/twitter/api/getPostsByMention.ts @@ -8,6 +8,8 @@ import { import { handleTwitterError } from './errorHandler' import { IProcessStreamContext } from '../../../types' +const MAX_HISTORICAL_30_DAYS_IN_SECONDS = 2592000 + /** * Get paginated posts by mention * @param input Input parameters @@ -33,6 +35,9 @@ const getPostsByMention = async ( ...(!ctx.onboarding && { start_time: new Date(Date.now() - maxRetrospectInSeconds * 1000).toISOString(), }), + ...(ctx.onboarding && { + start_time: new Date(Date.now() - MAX_HISTORICAL_30_DAYS_IN_SECONDS * 1000).toISOString(), + }), }, headers: { Authorization: `Bearer ${input.token}`, diff --git a/services/libs/integrations/src/integrations/youtube/api/comments.ts b/services/libs/integrations/src/integrations/youtube/api/comments.ts new file mode 100644 index 0000000000..9f9a0de3f0 --- /dev/null +++ b/services/libs/integrations/src/integrations/youtube/api/comments.ts @@ -0,0 +1,35 @@ +import axios, { AxiosRequestConfig } from 'axios' +import { YoutubeVideoStreamConfig, YoutubeCommentThreadSearch } from '../types' +import { IProcessStreamContext } from '@/types' + +export const getComments = async (ctx: IProcessStreamContext): Promise => { + const videoConfig = ctx.stream.data as YoutubeVideoStreamConfig + + try { + const getThreadedCommentsConfig: AxiosRequestConfig = { + method: 'get', + url: `https://www.googleapis.com/youtube/v3/commentThreads`, + params: { + key: videoConfig.apiKey, + videoId: videoConfig.videoId, + order: 'time', + maxResults: 100, + part: 'snippet', + }, + } + + const shouldLoadNextPage = videoConfig.nextPageToken && videoConfig.nextPageToken != '' + if (shouldLoadNextPage) { + getThreadedCommentsConfig.params.pageToken = videoConfig.nextPageToken + } + + const response = (await axios(getThreadedCommentsConfig)).data + return response + } catch (err) { + ctx.log.error( + { err, videoConfig }, + 'Error while using the youtube comments api to get a video comments', + ) + throw err + } +} diff --git a/services/libs/integrations/src/integrations/youtube/api/videos.ts b/services/libs/integrations/src/integrations/youtube/api/videos.ts new file mode 100644 index 0000000000..1d0394ece0 --- /dev/null +++ b/services/libs/integrations/src/integrations/youtube/api/videos.ts @@ -0,0 +1,36 @@ +import axios, { AxiosRequestConfig } from 'axios' +import { YoutubeIntegrationStreamConfig, YoutubeVideoSearch } from '../types' +import { IProcessStreamContext } from '@/types' + +export const getVideos = async (ctx: IProcessStreamContext): Promise => { + const channelSettings = ctx.stream.data as YoutubeIntegrationStreamConfig + + try { + const getChannelVideosConfig: AxiosRequestConfig = { + method: 'get', + url: `https://www.googleapis.com/youtube/v3/search`, + params: { + key: channelSettings.apiKey, + channelId: channelSettings.channelId, + type: 'video', + order: 'date', + maxResults: 50, + part: 'snippet', + }, + } + + const shouldLoadNextPage = channelSettings.nextPageToken && channelSettings.nextPageToken != '' + if (shouldLoadNextPage) { + getChannelVideosConfig.params.pageToken = channelSettings.nextPageToken + } + + const response = (await axios(getChannelVideosConfig)).data + return response + } catch (err) { + ctx.log.error( + { err, channelSettings }, + 'Error while using the youtube search api to get videos', + ) + throw err + } +} diff --git a/services/libs/integrations/src/integrations/youtube/api/videosByKeywords.ts b/services/libs/integrations/src/integrations/youtube/api/videosByKeywords.ts new file mode 100644 index 0000000000..d4e04570ec --- /dev/null +++ b/services/libs/integrations/src/integrations/youtube/api/videosByKeywords.ts @@ -0,0 +1,48 @@ +import axios, { AxiosRequestConfig } from 'axios' +import { YoutubeIntegrationStreamConfig, YoutubeVideoSearch } from '../types' +import { IProcessStreamContext } from '@/types' + +export const getVideosByKeywords = async ( + ctx: IProcessStreamContext +): Promise => { + const channelSettings = ctx.stream.data as YoutubeIntegrationStreamConfig + + const now = new Date() + const publishedAfter = new Date(now.getTime() - 1000 * 60 * 60 * 24 * 30) // 30 days + + try { + const getVideosByKeywordsRequestConfig: AxiosRequestConfig = { + method: 'get', + url: `https://www.googleapis.com/youtube/v3/search`, + params: { + key: channelSettings.apiKey, + type: 'video', + order: 'date', + maxResults: 50, + publishedAfter: publishedAfter.toISOString(), + part: 'snippet', + }, + } + + const includesKeywords = channelSettings.keywords && channelSettings.keywords.length > 0 + if (includesKeywords) { + // URL escape pipe(|) for the OR operator + getVideosByKeywordsRequestConfig.params.q = channelSettings.keywords.join('%7C') + } + + const shouldLoadNextPage = channelSettings.nextPageToken && channelSettings.nextPageToken != '' + if (shouldLoadNextPage) { + getVideosByKeywordsRequestConfig.params.pageToken = channelSettings.nextPageToken + } + + const response = (await axios(getVideosByKeywordsRequestConfig)).data + return response + } catch (err) { + // we've hit the limits for gettings anymore data or there's an error, anyways just log it + ctx.log.error( + { err, channelSettings }, + 'Error while using the youtube search api to get videos', + ) + throw err + } +} diff --git a/services/libs/integrations/src/integrations/youtube/generateStreams.ts b/services/libs/integrations/src/integrations/youtube/generateStreams.ts new file mode 100644 index 0000000000..b8e02b50b0 --- /dev/null +++ b/services/libs/integrations/src/integrations/youtube/generateStreams.ts @@ -0,0 +1,29 @@ +// generateStreams.ts content +import { YoutubeRootStream, YoutubeIntegrationStreamConfig } from './types' +import { GenerateStreamsHandler } from '../../types' + +const handler: GenerateStreamsHandler = async (ctx) => { + const channelSettings = ctx.integration.settings as YoutubeIntegrationStreamConfig + + if (!channelSettings.apiKey) { + await ctx.abortRunWithError('Api key must be provided') + return + } + + if (channelSettings.keywords && channelSettings.keywords.length > 0) { + const searchQuery = channelSettings.keywords.join('|') + await ctx.publishStream( + `${YoutubeRootStream.KEYWORDS_SEARCH}:${searchQuery}`, + channelSettings + ) + } else if (channelSettings.channelId != '') { + await ctx.publishStream( + `${YoutubeRootStream.UPLOADED_VIDEOS}:${channelSettings.channelId}`, + channelSettings + ) + } else { + await ctx.abortRunWithError('No channel id or keywords provided') + } +} + +export default handler diff --git a/services/libs/integrations/src/integrations/youtube/grid.ts b/services/libs/integrations/src/integrations/youtube/grid.ts new file mode 100644 index 0000000000..7e1c2f45a8 --- /dev/null +++ b/services/libs/integrations/src/integrations/youtube/grid.ts @@ -0,0 +1,10 @@ +// grid.ts content +import { IActivityScoringGrid } from '@crowd/types' +import { YoutubeActivityType } from './types' + +export const Youtube_GRID: Record = { + [YoutubeActivityType.COMMENT]: { + score: 6, + isContribution: true + } +} diff --git a/services/libs/integrations/src/integrations/youtube/index.ts b/services/libs/integrations/src/integrations/youtube/index.ts new file mode 100644 index 0000000000..c8b1c72ce1 --- /dev/null +++ b/services/libs/integrations/src/integrations/youtube/index.ts @@ -0,0 +1,22 @@ +// index.ts content +import { IIntegrationDescriptor } from '../../types' +import generateStreams from './generateStreams' +import { YOUTUBE_MEMBER_ATTRIBUTES } from './memberAttributes' +import processStream from './processStream' +import processData from './processData' +import { PlatformType } from '@crowd/types' + +const descriptor: IIntegrationDescriptor = { + type: PlatformType.YOUTUBE, + memberAttributes: YOUTUBE_MEMBER_ATTRIBUTES, + checkEvery: 360, + generateStreams, + processStream, + processData, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + postProcess: (settings: any) => { + return settings + }, +} + +export default descriptor diff --git a/services/libs/integrations/src/integrations/youtube/memberAttributes.ts b/services/libs/integrations/src/integrations/youtube/memberAttributes.ts new file mode 100644 index 0000000000..4968021270 --- /dev/null +++ b/services/libs/integrations/src/integrations/youtube/memberAttributes.ts @@ -0,0 +1,24 @@ +// memberAttributes.ts content +import { + IMemberAttribute, + MemberAttributeName, + MemberAttributeType, + MemberAttributes, +} from '@crowd/types' + +export const YOUTUBE_MEMBER_ATTRIBUTES: IMemberAttribute[] = [ + { + name: MemberAttributes[MemberAttributeName.SOURCE_ID].name, + label: MemberAttributes[MemberAttributeName.SOURCE_ID].label, + type: MemberAttributeType.STRING, + canDelete: false, + show: false, + }, + { + name: MemberAttributes[MemberAttributeName.URL].name, + label: MemberAttributes[MemberAttributeName.URL].label, + type: MemberAttributeType.STRING, + canDelete: false, + show: true, + } +] diff --git a/services/libs/integrations/src/integrations/youtube/processData.ts b/services/libs/integrations/src/integrations/youtube/processData.ts new file mode 100644 index 0000000000..08333a730d --- /dev/null +++ b/services/libs/integrations/src/integrations/youtube/processData.ts @@ -0,0 +1,65 @@ +// processData.ts content +import {IActivityData, IMemberData, MemberAttributeName, PlatformType } from '@crowd/types' +import { YoutubeVideoStreamConfig, YoutubeComment, YoutubeActivityType, YoutubeCommentThreadSearch} from './types' +import { ProcessDataHandler, IProcessDataContext} from '../../types' +import { Youtube_GRID } from './grid' + +const handler: ProcessDataHandler = async (ctx) => { + const data = ctx.data as {video: YoutubeVideoStreamConfig, comments: YoutubeCommentThreadSearch} + const comments = data.comments + const video = data.video + + for (const comment of comments.items) { + const singleComment = comment.snippet.topLevelComment + await processComment(ctx, video, singleComment) + } +} + +async function processComment( + ctx: IProcessDataContext, + video: YoutubeVideoStreamConfig, + comment: YoutubeComment +) { + const member = getMember(comment) + const scoring = Youtube_GRID[YoutubeActivityType.COMMENT] + + const parentCommentUrl = `https://www.youtube.com/watch?v=${video.videoId}&lc=${comment.id}` + const activity: IActivityData = { + type: YoutubeActivityType.COMMENT, + timestamp: comment.snippet.publishedAt, + sourceId: comment.id, + score: scoring.score, + isContribution: scoring.isContribution, + body: comment.snippet.textOriginal, + url: parentCommentUrl, + attributes: { + videoUrl: `https://www.youtube.com/watch?v=${video.videoId}`, + videoTitle: video.title, + authorChannelUrl: comment.snippet.authorChannelUrl + }, + member + } + await ctx.publishActivity(activity) +} + +function getMember(comment: YoutubeComment): IMemberData { + const member: IMemberData = { + displayName: comment.snippet.authorDisplayName, + identities: [ + { + platform: PlatformType.YOUTUBE, + sourceId: comment.snippet.authorChannelId.value, + username: comment.snippet.authorChannelId.value + }, + ], + attributes: { + [MemberAttributeName.URL]: { + [PlatformType.YOUTUBE]: comment.snippet.authorChannelUrl, + }, + }, + } + + return member +} + +export default handler diff --git a/services/libs/integrations/src/integrations/youtube/processStream.ts b/services/libs/integrations/src/integrations/youtube/processStream.ts new file mode 100644 index 0000000000..517923e215 --- /dev/null +++ b/services/libs/integrations/src/integrations/youtube/processStream.ts @@ -0,0 +1,98 @@ +// processStream.ts content +import { YoutubeRootStream, YoutubeIntegrationStreamConfig, YoutubeVideoStreamConfig } from './types' +import { getVideos } from './api/videos' +import { getComments } from './api/comments' +import { getVideosByKeywords } from './api/videosByKeywords' +import { IProcessStreamContext, ProcessStreamHandler } from '../../types' + +const handler: ProcessStreamHandler = async (ctx) => { + const isChannelVideoStream = ctx.stream.identifier.startsWith(YoutubeRootStream.CHANNEL_VIDEO) + // if it's keywords search stream or videos stream make sure to fetch at most 40 pages + if (!isChannelVideoStream) { + const channelSettings = ctx.stream.data as YoutubeIntegrationStreamConfig + if (Number(channelSettings.page) >= 41) { + await ctx.log.info(`Finished fetching the maximum number of youtube pages for ${channelSettings.apiKey} at ${Date.now()}`) + return + } + } + + if (ctx.stream.identifier.startsWith(YoutubeRootStream.UPLOADED_VIDEOS)) { + await handleChannelStream(ctx) + } else if (ctx.stream.identifier.startsWith(YoutubeRootStream.KEYWORDS_SEARCH)) { + await handleKeywordsSearchStream(ctx) + } else if (isChannelVideoStream) { + await handleVideoStream(ctx) + } +} + +async function handleChannelStream(ctx: IProcessStreamContext) { + const channelSettings = ctx.stream.data as YoutubeIntegrationStreamConfig + const videos = await getVideos(ctx) + + for (const video of videos.items) { + const videoId = video.id.videoId + + await ctx.publishStream(`${YoutubeRootStream.CHANNEL_VIDEO}:${videoId}`, { + title: video.snippet.title, + videoId, + apiKey: channelSettings.apiKey + }) + } + + const shouldLoadNextPage = videos.nextPageToken && videos.nextPageToken != '' + if (shouldLoadNextPage) { + await ctx.publishStream( + `${YoutubeRootStream.UPLOADED_VIDEOS}:${channelSettings.channelId}:${videos.nextPageToken}`, + { + ...channelSettings, + page: channelSettings.page + 1, + nextPageToken: videos.nextPageToken + }, + ) + } +} + +async function handleKeywordsSearchStream(ctx: IProcessStreamContext) { + const channelSettings = ctx.stream.data as YoutubeIntegrationStreamConfig + + const videos = await getVideosByKeywords(ctx) + for (const video of videos.items) { + const videoId = video.id.videoId + + await ctx.publishStream(`${YoutubeRootStream.CHANNEL_VIDEO}:${videoId}`, { + title: video.snippet.title, + videoId, + apiKey: channelSettings.apiKey + }) + } + + const shouldLoadNextPage = videos.nextPageToken && videos.nextPageToken != '' + if (shouldLoadNextPage) { + const searchQuery = channelSettings.keywords.join('|') + await ctx.publishStream( + `${YoutubeRootStream.KEYWORDS_SEARCH}:${searchQuery}:${videos.nextPageToken}`, + { + ...channelSettings, + page: channelSettings.page + 1, + nextPageToken: videos.nextPageToken + } + ) + } +} + +async function handleVideoStream(ctx: IProcessStreamContext) { + const videoConfig = ctx.stream.data as YoutubeVideoStreamConfig + const comments = await getComments(ctx) + + await ctx.publishData({ video: videoConfig, comments: comments }) + + const shouldLoadNextPage = comments.nextPageToken && comments.nextPageToken != '' + if (shouldLoadNextPage) { + await ctx.publishStream(`${YoutubeRootStream.CHANNEL_VIDEO}:${videoConfig.videoId}:${comments.nextPageToken}`, { + ...videoConfig, + nextPageToken: comments.nextPageToken + }) + } +} + +export default handler diff --git a/services/libs/integrations/src/integrations/youtube/types.ts b/services/libs/integrations/src/integrations/youtube/types.ts new file mode 100644 index 0000000000..1f78e22a3e --- /dev/null +++ b/services/libs/integrations/src/integrations/youtube/types.ts @@ -0,0 +1,114 @@ +// types.ts content +export enum YoutubeActivityType { + COMMENT = 'comment', +} + +export enum YoutubeRootStream { + UPLOADED_VIDEOS = 'uploaded_videos', + CHANNEL_VIDEO = 'channel_video', + KEYWORDS_SEARCH = 'keywords_search' +} + +export interface YoutubeIntegrationStreamConfig { + apiKey: string + channelId: string + nextPageToken?: string + keywords: string[] + page: number +} + +export interface YoutubeVideoStreamConfig { + videoId: string + apiKey: string + title: string + nextPageToken?: string +} + +export interface YoutubeVideoSearch { + kind: string + etag: string + nextPageToken: string + regionCode: string + pageInfo: { + totalResults: number + resultsPerPage: number + } + items: YoutubeChannelSearchItem[] +} + +interface YoutubeChannelSearchItem { + kind: string + etag: string + id: { + kind: string + videoId: string + }, + snippet: { + publishedAt: string + channelId: string + title: string + description: string + thumbnails: { + default: YoutubeThumbnail + medium: YoutubeThumbnail + high: YoutubeThumbnail + }, + channelTitle: string + liveBroadcastContent: string + } +} + +interface YoutubeThumbnail { + url: string + width: number + height: number +} + + +export interface YoutubeCommentThreadSearch { + kind: string + etag: string + nextPageToken: string + pageInfo: { + totalResults: number + resultsPerPage: number + }, + items: YoutubeCommentThread[] +} + +export interface YoutubeCommentThread { + kind: string + etag: string + id: string + snippet: { + channelId?: string + videoId: string + topLevelComment: YoutubeComment + }, + canReply: boolean + totalReplyCount: number + isPublic: boolean +} + +export interface YoutubeComment { + kind: string + etag: string + id: string + snippet: { + authorDisplayName: string + authorProfileImageUrl: string + authorChannelUrl: string + authorChannelId: { + value: string + }, + channelId?: string + videoId: string + textDisplay: string + textOriginal: string + canRate: boolean + viewerRating: string + likeCount: number + publishedAt: string + updatedAt: string + } +} diff --git a/services/libs/integrations/src/types.ts b/services/libs/integrations/src/types.ts index 7ac9ffbeba..5807f494b9 100644 --- a/services/libs/integrations/src/types.ts +++ b/services/libs/integrations/src/types.ts @@ -1,21 +1,19 @@ +import { DbConnection, DbTransaction } from '@crowd/database' +import { Logger } from '@crowd/logging' import { - IMemberAttribute, - IActivityData, - IntegrationResultType, Entity, + IActivityData, IAutomationData, -} from '@crowd/types' -import { Logger } from '@crowd/logging' -import { ICache, + IConcurrentRequestLimiter, IIntegration, IIntegrationStream, + IIntegrationSyncWorkerEmitter, + IMemberAttribute, IRateLimiter, - IConcurrentRequestLimiter, + IntegrationResultType, } from '@crowd/types' -import { DbConnection, DbTransaction } from '@crowd/database' -import { IntegrationSyncWorkerEmitter } from '@crowd/sqs' import { IBatchOperationResult } from './integrations/premium/hubspot/api/types' export interface IIntegrationContext { @@ -36,7 +34,7 @@ export interface IIntegrationContext { } export interface IIntegrationStartRemoteSyncContext { - integrationSyncWorkerEmitter: IntegrationSyncWorkerEmitter + integrationSyncWorkerEmitter: IIntegrationSyncWorkerEmitter integration: IIntegration automations: IAutomationData[] tenantId: string diff --git a/services/libs/logging/src/logger.ts b/services/libs/logging/src/logger.ts index 7ba72d0da6..68c1ab4811 100644 --- a/services/libs/logging/src/logger.ts +++ b/services/libs/logging/src/logger.ts @@ -24,6 +24,10 @@ export const getServiceLogger = (): Logger => { } serviceLoggerInstance = Bunyan.createLogger(options) + if (!IS_DEV_ENV && !IS_TEST_ENV) { + delete serviceLoggerInstance.fields.hostname + } + return serviceLoggerInstance } diff --git a/services/libs/opensearch/src/apiClient.ts b/services/libs/opensearch/src/apiClient.ts index 2c6470186f..d54e45081f 100644 --- a/services/libs/opensearch/src/apiClient.ts +++ b/services/libs/opensearch/src/apiClient.ts @@ -32,7 +32,10 @@ export class SearchSyncApiClient { }) } - public async triggerOrganizationMembersSync(organizationId: string): Promise { + public async triggerOrganizationMembersSync( + tenantId: string, + organizationId: string, + ): Promise { if (!organizationId) { throw new Error('organizationId is required!') } @@ -82,7 +85,10 @@ export class SearchSyncApiClient { }) } - public async triggerOrganizationActivitiesSync(organizationId: string): Promise { + public async triggerOrganizationActivitiesSync( + tenantId: string, + organizationId: string, + ): Promise { if (!organizationId) { throw new Error('organizationId is required!') } diff --git a/services/libs/opensearch/src/memberTranslator.ts b/services/libs/opensearch/src/memberTranslator.ts index edd112e2d1..982ddc1bc8 100644 --- a/services/libs/opensearch/src/memberTranslator.ts +++ b/services/libs/opensearch/src/memberTranslator.ts @@ -49,12 +49,33 @@ export default class MemberTranslator extends FieldTranslator { // tags this.translations.name = 'string_name' + // contributions + this.translations.url = 'string_url' + this.translations.topics = 'string_arr_topics' + this.translations.summary = 'string_summary' + this.translations.numberCommits = 'int_numberCommits' + this.translations.lastCommitDate = 'date_lastCommitDate' + this.translations.firstCommitDate = 'date_firstCommitDate' + + // affiliations + this.translations.segmentId = 'string_segmentId' + this.translations.segmentSlug = 'string_segmentSlug' + this.translations.segmentName = 'string_segmentName' + this.translations.segmentParentName = 'string_segmentParentName' + this.translations.organizationId = 'string_organizationId' + this.translations.organizationName = 'string_organizationName' + this.translations.organizationLogo = 'string_organizationLogo' + this.translations.dateStart = 'date_dateStart' + this.translations.dateEnd = 'date_dateEnd' + // organizations this.translations.logo = 'string_logo' + this.translations.website = 'string_website' this.translations.memberOrganizations = 'obj_memberOrganizations' this.translations.title = 'string_title' this.translations.dateStart = 'date_dateStart' this.translations.dateEnd = 'date_dateEnd' + this.translations.source = 'string_source' // identities this.translations.platform = 'string_platform' @@ -64,9 +85,6 @@ export default class MemberTranslator extends FieldTranslator { // fix for colliding translations of id -> uuid_memberId (members) and id -> uuid_id (organizations, tags) this.opensearchToCrowdMap.set('uuid_id', 'id') - - // backwards compatibility for reach.total - this.crowdToOpensearchMap.set('reach.total', 'int_totalReach') } private attributeTypeToOpenSearchPrefix(type: MemberAttributeType): string { diff --git a/services/libs/opensearch/src/models/members.ts b/services/libs/opensearch/src/models/members.ts index 1222b2eaca..6f1abbac1b 100644 --- a/services/libs/opensearch/src/models/members.ts +++ b/services/libs/opensearch/src/models/members.ts @@ -39,11 +39,8 @@ export class MembersOpensearch extends OpensearchModelBase { type: OpensearchFieldType.BOOL, }, reach: { - type: OpensearchFieldType.INT, - customTranslation: { - toOpensearch: 'int_totalReach', - fromOpensearch: 'int_totalReach', - }, + type: OpensearchFieldType.OBJECT, + preventNestedFieldTranslation: true, }, numberOfOpenSourceContributions: { type: OpensearchFieldType.INT, @@ -89,6 +86,20 @@ export class MembersOpensearch extends OpensearchModelBase { fromOpensearch: 'nested_tags', }, }, + contributions: { + type: OpensearchFieldType.NESTED, + customTranslation: { + toOpensearch: 'nested_contributions.uuid_id', + fromOpensearch: 'nested_contributions', + }, + }, + affiliations: { + type: OpensearchFieldType.NESTED, + customTranslation: { + toOpensearch: 'nested_affiliations.uuid_id', + fromOpensearch: 'nested_affiliations', + }, + }, organizations: { type: OpensearchFieldType.NESTED, customTranslation: { @@ -96,5 +107,19 @@ export class MembersOpensearch extends OpensearchModelBase { fromOpensearch: 'nested_organizations', }, }, + notes: { + type: OpensearchFieldType.NESTED, + customTranslation: { + toOpensearch: 'nested_notes.uuid_id', + fromOpensearch: 'nested_notes', + }, + }, + tasks: { + type: OpensearchFieldType.NESTED, + customTranslation: { + toOpensearch: 'nested_tasks.uuid_id', + fromOpensearch: 'nested_tasks', + }, + }, } } diff --git a/services/libs/opensearch/src/models/organizations.ts b/services/libs/opensearch/src/models/organizations.ts index fe591f5c45..bb35dfb193 100644 --- a/services/libs/opensearch/src/models/organizations.ts +++ b/services/libs/opensearch/src/models/organizations.ts @@ -19,6 +19,7 @@ export class OrganizationsOpensearch extends OpensearchModelBase { }, address: { type: OpensearchFieldType.OBJECT, + preventNestedFieldTranslation: true, }, logo: { type: OpensearchFieldType.STRING, @@ -41,8 +42,16 @@ export class OrganizationsOpensearch extends OpensearchModelBase { tags: { type: OpensearchFieldType.STRING_ARR, }, + naics: { + type: OpensearchFieldType.OBJECT, + preventNestedFieldTranslation: true, + }, + ticker: { + type: OpensearchFieldType.STRING, + }, employeeCountByCountry: { type: OpensearchFieldType.OBJECT, + preventNestedFieldTranslation: true, }, employees: { type: OpensearchFieldType.INT, @@ -124,10 +133,17 @@ export class OrganizationsOpensearch extends OpensearchModelBase { identities: { type: OpensearchFieldType.NESTED, customTranslation: { - toOpensearch: 'nested_identities.string_name', + toOpensearch: 'nested_identities.string_platform', fromOpensearch: 'nested_identities', }, }, + weakIdentities: { + type: OpensearchFieldType.NESTED, + customTranslation: { + toOpensearch: 'nested_weakIdentities.string_name', + fromOpensearch: 'nested_weakIdentities', + }, + }, isTeamOrganization: { type: OpensearchFieldType.BOOL, }, @@ -135,10 +151,10 @@ export class OrganizationsOpensearch extends OpensearchModelBase { type: OpensearchFieldType.BOOL, }, immediateParent: { - type: OpensearchFieldType.STRING_ARR, + type: OpensearchFieldType.STRING, }, ultimateParent: { - type: OpensearchFieldType.STRING_ARR, + type: OpensearchFieldType.STRING, }, affiliatedProfiles: { type: OpensearchFieldType.STRING_ARR, @@ -154,12 +170,15 @@ export class OrganizationsOpensearch extends OpensearchModelBase { }, averageEmployeeTenure: { type: OpensearchFieldType.FLOAT, + preventNestedFieldTranslation: true, }, averageTenureByLevel: { type: OpensearchFieldType.OBJECT, + preventNestedFieldTranslation: true, }, averageTenureByRole: { type: OpensearchFieldType.OBJECT, + preventNestedFieldTranslation: true, }, directSubsidiaries: { type: OpensearchFieldType.STRING_ARR, @@ -170,6 +189,7 @@ export class OrganizationsOpensearch extends OpensearchModelBase { }, employeeCountByMonth: { type: OpensearchFieldType.OBJECT, + preventNestedFieldTranslation: true, }, employeeGrowthRate: { type: OpensearchFieldType.OBJECT, @@ -177,18 +197,22 @@ export class OrganizationsOpensearch extends OpensearchModelBase { }, employeeCountByMonthByLevel: { type: OpensearchFieldType.OBJECT, + preventNestedFieldTranslation: true, }, employeeCountByMonthByRole: { type: OpensearchFieldType.OBJECT, + preventNestedFieldTranslation: true, }, gicsSector: { - type: OpensearchFieldType.STRING_ARR, + type: OpensearchFieldType.STRING, }, grossAdditionsByMonth: { type: OpensearchFieldType.OBJECT, + preventNestedFieldTranslation: true, }, grossDeparturesByMonth: { type: OpensearchFieldType.OBJECT, + preventNestedFieldTranslation: true, }, employeeChurnRate12Month: { type: OpensearchFieldType.FLOAT, @@ -196,5 +220,8 @@ export class OrganizationsOpensearch extends OpensearchModelBase { employeeGrowthRate12Month: { type: OpensearchFieldType.FLOAT, }, + manuallyChangedFields: { + type: OpensearchFieldType.STRING_ARR, + }, } } diff --git a/services/libs/opensearch/src/organizationTranslator.ts b/services/libs/opensearch/src/organizationTranslator.ts index 9806fe9b18..5ae4001b4e 100644 --- a/services/libs/opensearch/src/organizationTranslator.ts +++ b/services/libs/opensearch/src/organizationTranslator.ts @@ -17,6 +17,10 @@ export default class OrganizationTranslator extends FieldTranslator { return acc }, {}) + // weakIdentities + this.translations.integrationId = 'uuid_integrationId' + this.translations.sourceId = 'uuid_sourceId' + // identities this.translations.platform = 'string_platform' this.translations.name = 'string_name' diff --git a/services/libs/opensearch/src/repo/activity.data.ts b/services/libs/opensearch/src/repo/activity.data.ts index 753071ad39..063457bc8c 100644 --- a/services/libs/opensearch/src/repo/activity.data.ts +++ b/services/libs/opensearch/src/repo/activity.data.ts @@ -22,4 +22,5 @@ export interface IDbActivitySyncData { username: string objectMemberId: string | null objectMemberUsername: string | null + organizationId: string | null } diff --git a/services/libs/opensearch/src/repo/activity.repo.ts b/services/libs/opensearch/src/repo/activity.repo.ts index 1123834b04..cc7f316c90 100644 --- a/services/libs/opensearch/src/repo/activity.repo.ts +++ b/services/libs/opensearch/src/repo/activity.repo.ts @@ -20,7 +20,6 @@ export class ActivityRepository extends RepositoryBase { score, "sourceId", "sourceParentId", - attributes, channel, body, title, @@ -32,7 +31,8 @@ export class ActivityRepository extends RepositoryBase { "parentId", username, "objectMemberId", - "objectMemberUsername" + "objectMemberUsername", + "organizationId" from activities where id in ($(activityIds:csv)) and "deletedAt" is null `, { diff --git a/services/libs/opensearch/src/repo/member.data.ts b/services/libs/opensearch/src/repo/member.data.ts index 1f6dd8bf49..e29aa0fc78 100644 --- a/services/libs/opensearch/src/repo/member.data.ts +++ b/services/libs/opensearch/src/repo/member.data.ts @@ -8,17 +8,56 @@ export interface IDbMemberTagData { name: string } +export interface IDbMemberNoteData { + id: string + body: string +} + +export interface IDbMemberTaskData { + id: string + name: string + body: string + status: string + dueDate: string + type: string +} + export interface IDbMemberOrganization { id: string logo: string | null + website: string | null displayName: string | null memberOrganizations: { title: string dateStart: string dateEnd: string + source?: string } } +export interface IDbMemberAffiliationData { + id: string + segmentId: string + segmentSlug: string + segmentName: string + segmentParentName: string + organizationId: string + organizationName: string + organizationLogo: string + dateStart: string + dateEnd: string +} + +export interface IDbMemberContributionData { + id: string + url: string + topics: string[] | null + summary: string | null + numberCommits: number + lastCommitDate: string + firstCommitDate: string +} + export interface IDbMemberSyncData { id: string tenantId: string @@ -31,7 +70,7 @@ export interface IDbMemberSyncData { joinedAt: string createdAt: string manuallyCreated: boolean - totalReach: number + reach: unknown | null numberOfOpenSourceContributions: number // member activity data @@ -42,11 +81,16 @@ export interface IDbMemberSyncData { lastActive: string averageSentiment: number | null + contributions: IDbMemberContributionData[] + affiliations: IDbMemberAffiliationData[] identities: IDbMemberIdentityData[] + weakIdentities: IDbMemberIdentityData[] organizations: IDbMemberOrganization[] tags: IDbMemberTagData[] toMergeIds: string[] noMergeIds: string[] + notes: IDbMemberNoteData[] + tasks: IDbMemberTaskData[] } export interface IMemberSegmentMatrixItem { diff --git a/services/libs/opensearch/src/repo/member.repo.ts b/services/libs/opensearch/src/repo/member.repo.ts index f472ae67db..a9b468e826 100644 --- a/services/libs/opensearch/src/repo/member.repo.ts +++ b/services/libs/opensearch/src/repo/member.repo.ts @@ -252,11 +252,66 @@ export class MemberRepository extends RepositoryBase { end)::numeric, 2) as "averageSentiment" from activities a where a."memberId" in ($(ids:csv)) - group by a."memberId", a."segmentId") + group by a."memberId", a."segmentId"), + member_affiliations as ( + select msa."memberId", + json_agg( + json_build_object( + 'id', msa.id, + 'segmentId', s.id, + 'segmentSlug', s.slug, + 'segmentName', s.name, + 'segmentParentName', s."parentName", + 'organizationId', o.id, + 'organizationName', o."displayName", + 'organizationLogo', o.logo, + 'dateStart', msa."dateStart", + 'dateEnd', msa."dateEnd" + ) + ) as all_affiliations, + jsonb_agg(msa.id) as all_ids + from "memberSegmentAffiliations" msa + left join organizations o on o.id = msa."organizationId" + inner join segments s on s.id = msa."segmentId" + where msa."memberId" = $(memberId) + group by msa."memberId"), + member_notes as ( + select mn."memberId", + json_agg( + json_build_object( + 'id', n.id, + 'body', n.body + ) + ) as all_notes, + jsonb_agg(n.id) as all_ids + from "memberNotes" mn + inner join notes n on mn."noteId" = n.id + where mn."memberId" = $(memberId) + and n."deletedAt" is null + group by mn."memberId"), + member_tasks as ( + select mtk."memberId", + json_agg( + json_build_object( + 'id', tk.id, + 'name', tk.name, + 'body', tk.body, + 'status', tk.status, + 'dueDate', tk."dueDate", + 'type', tk.type + ) + ) as all_tasks, + jsonb_agg(tk.id) as all_ids + from "memberTasks" mtk + inner join tasks tk on mtk."taskId" = tk.id + where mtk."memberId" = $(memberId) + and tk."deletedAt" is null + group by mtk."memberId") select m.id, m."tenantId", ms."segmentId", m."displayName", + coalesce(m.contributions, '[]'::jsonb) as contributions, m.attributes, m.emails, m.score, @@ -264,7 +319,7 @@ export class MemberRepository extends RepositoryBase { m."joinedAt", m."manuallyCreated", m."createdAt", - (m.reach -> 'total')::integer as "totalReach", + m.reach, coalesce(jsonb_array_length(m.contributions), 0) as "numberOfOpenSourceContributions", ad."activeOn", @@ -277,6 +332,9 @@ export class MemberRepository extends RepositoryBase { i.identities, coalesce(mo.all_organizations, json_build_array()) as organizations, coalesce(mt.all_tags, json_build_array()) as tags, + coalesce(ma.all_affiliations, json_build_array()) as affiliations, + coalesce(mn.all_notes, json_build_array()) as notes, + coalesce(mtk.all_tasks, json_build_array()) as tasks, coalesce(tmd.to_merge_ids, array []::text[]) as "toMergeIds", coalesce(nmd.no_merge_ids, array []::text[]) as "noMergeIds" from "memberSegments" ms @@ -285,8 +343,11 @@ export class MemberRepository extends RepositoryBase { left join activity_data ad on ms."memberId" = ad."memberId" and ms."segmentId" = ad."segmentId" left join to_merge_data tmd on m.id = tmd."memberId" left join no_merge_data nmd on m.id = nmd."memberId" + left join member_affiliations ma on m.id = ma."memberId" left join member_tags mt on ms."memberId" = mt."memberId" left join member_organizations mo on ms."memberId" = mo."memberId" and ms."segmentId" = mo."segmentId" + left join member_notes mn on ms."memberId" = mn."memberId" + left join member_tasks mtk on ms."memberId" = mtk."memberId" where ms."memberId" in ($(ids:csv)) and m."deletedAt" is null and (ad."memberId" is not null or m."manuallyCreated");`, @@ -340,10 +401,12 @@ export class MemberRepository extends RepositoryBase { json_build_object( 'id', o.id, 'logo', o.logo, + 'website', o.website, 'displayName', o."displayName", 'memberOrganizations', json_build_object( 'dateStart', mo."dateStart", 'dateEnd', mo."dateEnd", + 'source', mo."source", 'title', mo.title ) ) @@ -354,11 +417,6 @@ export class MemberRepository extends RepositoryBase { where mo."memberId" = $(memberId) and mo."deletedAt" is null and o."deletedAt" is null - and exists (select 1 - from activities a - where a."memberId" = mo."memberId" - and a."organizationId" = mo."organizationId" - and a."segmentId" = $(segmentId)) group by mo."memberId"), identities as ( select mi."memberId", @@ -388,20 +446,75 @@ export class MemberRepository extends RepositoryBase { from activities a where a."memberId" = $(memberId) and a."segmentId" = $(segmentId) - group by a."memberId") + group by a."memberId"), + member_affiliations as ( + select msa."memberId", + json_agg( + json_build_object( + 'id', msa.id, + 'segmentId', s.id, + 'segmentSlug', s.slug, + 'segmentName', s.name, + 'segmentParentName', s."parentName", + 'organizationId', o.id, + 'organizationName', o."displayName", + 'organizationLogo', o.logo, + 'dateStart', msa."dateStart", + 'dateEnd', msa."dateEnd" + ) + ) as all_affiliations, + jsonb_agg(msa.id) as all_ids + from "memberSegmentAffiliations" msa + left join organizations o on o.id = msa."organizationId" + inner join segments s on s.id = msa."segmentId" + where msa."memberId" = $(memberId) + group by msa."memberId"), + member_notes as ( + select mn."memberId", + json_agg( + json_build_object( + 'id', n.id, + 'body', n.body + ) + ) as all_notes, + jsonb_agg(n.id) as all_ids + from "memberNotes" mn + inner join notes n on mn."noteId" = n.id + where mn."memberId" = $(memberId) + and n."deletedAt" is null + group by mn."memberId"), + member_tasks as ( + select mtk."memberId", + json_agg( + json_build_object( + 'id', tk.id, + 'name', tk.name, + 'body', tk.body, + 'status', tk.status, + 'dueDate', tk."dueDate", + 'type', tk.type + ) + ) as all_tasks, + jsonb_agg(tk.id) as all_ids + from "memberTasks" mtk + inner join tasks tk on mtk."taskId" = tk.id + where mtk."memberId" = $(memberId) + and tk."deletedAt" is null + group by mtk."memberId") select m.id, m."tenantId", $(segmentId) as "segmentId", m."displayName", m.attributes, + coalesce(m.contributions, '[]'::jsonb) as contributions, m.emails, m.score, m."lastEnriched", m."joinedAt", m."manuallyCreated", m."createdAt", - (m.reach -> 'total')::integer as "totalReach", + m.reach, coalesce(jsonb_array_length(m.contributions), 0) as "numberOfOpenSourceContributions", ad."activeOn", @@ -411,9 +524,13 @@ export class MemberRepository extends RepositoryBase { ad."lastActive", ad."averageSentiment", - i.identities, + coalesce(i.identities, '[]'::json) as "identities", + coalesce(m."weakIdentities", '[]'::jsonb) as "weakIdentities", coalesce(mo.all_organizations, json_build_array()) as organizations, coalesce(mt.all_tags, json_build_array()) as tags, + coalesce(ma.all_affiliations, json_build_array()) as affiliations, + coalesce(mn.all_notes, json_build_array()) as notes, + coalesce(mtk.all_tasks, json_build_array()) as tasks, coalesce(tmd.to_merge_ids, array []::text[]) as "toMergeIds", coalesce(nmd.no_merge_ids, array []::text[]) as "noMergeIds" from members m @@ -422,6 +539,9 @@ export class MemberRepository extends RepositoryBase { left join to_merge_data tmd on m.id = tmd."memberId" left join no_merge_data nmd on m.id = nmd."memberId" left join member_tags mt on m.id = mt."memberId" + left join member_affiliations ma on m.id = ma."memberId" + left join member_notes mn on m.id = mn."memberId" + left join member_tasks mtk on m.id = mtk."memberId" left join member_organizations mo on m.id = mo."memberId" where m.id = $(memberId) and m."deletedAt" is null diff --git a/services/libs/opensearch/src/repo/organization.data.ts b/services/libs/opensearch/src/repo/organization.data.ts index c76849cca2..d28225a1e3 100644 --- a/services/libs/opensearch/src/repo/organization.data.ts +++ b/services/libs/opensearch/src/repo/organization.data.ts @@ -58,6 +58,8 @@ export interface IDbOrganizationSyncData { employeeChurnRate12Month: number | null employeeGrowthRate12Month: number | null tags: string[] | null + ticker: string | null + manuallyChangedFields: string[] | null // aggregate data joinedAt: string diff --git a/services/libs/opensearch/src/repo/organization.repo.ts b/services/libs/opensearch/src/repo/organization.repo.ts index 0130eeccf8..a28bcef8b9 100644 --- a/services/libs/opensearch/src/repo/organization.repo.ts +++ b/services/libs/opensearch/src/repo/organization.repo.ts @@ -195,6 +195,8 @@ export class OrganizationRepository extends RepositoryBase '12_month', 'null')::decimal AS "employeeChurnRate12Month", nullif (o."employeeGrowthRate" -> '12_month', 'null')::decimal AS "employeeGrowthRate12Month", o.tags, @@ -250,19 +254,16 @@ export class OrganizationRepository extends RepositoryBase { const results = await this.db().any( ` - select distinct a."segmentId", a."organizationId" - from activities a - where a."organizationId" in ($(ids:csv)); + select distinct mo."organizationId", a."segmentId" + from "memberOrganizations" mo + inner join activities a on mo."memberId" = a."memberId" + where mo."organizationId" in ($(ids:csv)); `, { ids, diff --git a/services/libs/opensearch/src/service/activity.sync.service.ts b/services/libs/opensearch/src/service/activity.sync.service.ts index a7f0c9009b..e84aab047b 100644 --- a/services/libs/opensearch/src/service/activity.sync.service.ts +++ b/services/libs/opensearch/src/service/activity.sync.service.ts @@ -273,7 +273,6 @@ export class ActivitySyncService { p.int_score = data.score ?? 0 p.keyword_sourceId = data.sourceId p.keyword_sourceParentId = data.sourceParentId - p.string_attributes = data.attributes ? JSON.stringify(data.attributes) : '{}' p.keyword_channel = data.channel p.string_body = trimUtf8ToMaxByteLength(data.body, ActivitySyncService.MAX_BYTE_LENGTH) p.string_title = data.title @@ -286,6 +285,7 @@ export class ActivitySyncService { p.string_username = data.username p.uuid_objectMemberId = data.objectMemberId p.string_objectMemberUsername = data.objectMemberUsername + p.uuid_organizationId = data.organizationId return p } diff --git a/services/libs/opensearch/src/service/init.service.ts b/services/libs/opensearch/src/service/init.service.ts index cd919bbae3..c15d5c1052 100644 --- a/services/libs/opensearch/src/service/init.service.ts +++ b/services/libs/opensearch/src/service/init.service.ts @@ -50,6 +50,8 @@ export class InitService { employeeChurnRate12Month: 0.12, employeeGrowthRate12Month: 0.12, attributes: {}, + ticker: 'FAKE', + manuallyChangedFields: [], createdAt: new Date().toISOString(), description: 'Fake organization', displayName: 'Fake organization', @@ -166,7 +168,9 @@ export class InitService { lastEnriched: new Date().toISOString(), joinedAt: new Date().toISOString(), createdAt: new Date().toISOString(), - totalReach: 20, + reach: { + total: 20, + }, numberOfOpenSourceContributions: 10, activeOn: ['devto'], @@ -176,16 +180,50 @@ export class InitService { lastActive: new Date().toISOString(), averageSentiment: 20.32, + contributions: [ + { + id: '112529472', + url: 'https://github.com/bachman/pied-piper', + topics: ['compression', 'data', 'middle-out', 'Java'], + summary: 'Pied Piper: 10 commits in 1 day', + numberCommits: 10, + lastCommitDate: '2023-03-10', + firstCommitDate: '2023-03-01', + }, + ], + + affiliations: [ + { + id: '0dfaa9a0-d95a-4397-958e-4727189e3ef8', + segmentId: 'ce36b0b0-1fc4-4637-955d-afb8a6b58e48', + segmentSlug: 'test-segment', + segmentName: 'Test Segment', + segmentParentName: 'Test Parent Segment', + organizationId: 'b176d053-c53e-42d2-88d2-6fbc3e34184c', + organizationName: 'Test Organization', + organizationLogo: 'https://placehold.co/400', + dateStart: new Date().toISOString(), + dateEnd: new Date().toISOString(), + }, + ], + identities: [ { platform: 'devto', username: 'Test Member', }, ], + weakIdentities: [ + { + platform: 'github', + username: 'fakeWeakIdentity', + }, + ], organizations: [ { id: '0dfaa9a0-d95a-4397-958e-4727189e3ef8', logo: 'https://placehold.co/400', + website: 'https://example.com', displayName: 'Test Organization', memberOrganizations: { title: 'blabla', @@ -202,7 +240,22 @@ export class InitService { ], toMergeIds: ['3690742c-c5de-4d9a-aef8-1e3eaf57233d'], noMergeIds: ['b176d053-c53e-42d2-88d2-6fbc3e34184c'], - + notes: [ + { + id: 'b176d053-c53e-42d2-88d2-6fbc3e34184c', + body: 'This is a fake note 1', + }, + ], + tasks: [ + { + id: 'b176d053-c53e-42d2-88d2-6fbc3e34184c', + name: 'Fake Task 1', + body: 'This is a fake task 1', + status: 'completed', + dueDate: new Date().toISOString(), + type: 'type1', + }, + ], attributes: {}, manuallyCreated: false, } @@ -244,6 +297,7 @@ export class InitService { username: 'Test Member', objectMemberId: '4ea4c0f7-fdf8-448c-99ff-e03d0df95358', objectMemberUsername: 'Test Member2', + organizationId: '2badb0e5-e21b-4955-aba7-d52ef66bae59', } const prepared = ActivitySyncService.prefixData(fakeActivity) diff --git a/services/libs/opensearch/src/service/member.sync.service.ts b/services/libs/opensearch/src/service/member.sync.service.ts index 312c0b79df..89222098e0 100644 --- a/services/libs/opensearch/src/service/member.sync.service.ts +++ b/services/libs/opensearch/src/service/member.sync.service.ts @@ -592,6 +592,10 @@ export class MemberSyncService { member.averageSentiment = null member.tags = [] member.organizations = [] + member.contributions = [] + member.affiliations = [] + member.notes = [] + member.tasks = [] for (const m of members) { member.activeOn.push(...m.activeOn) @@ -615,6 +619,10 @@ export class MemberSyncService { } member.tags.push(...m.tags) member.organizations.push(...m.organizations) + member.contributions.push(...m.contributions) + member.affiliations.push(...m.affiliations) + member.notes.push(...m.notes) + member.tasks.push(...m.tasks) } // average sentiment with the total number of members that have sentiment set @@ -631,6 +639,10 @@ export class MemberSyncService { member.activityTypes = distinct(member.activityTypes) member.tags = distinctBy(member.tags, (t) => t.id) member.organizations = distinctBy(member.organizations, (o) => o.id) + member.contributions = distinctBy(member.contributions, (c) => c.id) + member.affiliations = distinctBy(member.affiliations, (a) => a.id) + member.notes = distinctBy(member.notes, (n) => n.id) + member.tasks = distinctBy(member.tasks, (t) => t.id) return member } @@ -673,14 +685,18 @@ export class MemberSyncService { } } + // If the 'reach' data from the database is a number instead of an object, + // we convert it into an object with a 'total' property holding the original number. + p.obj_reach = typeof data.reach === 'object' ? data.reach : { total: data.reach } + p.obj_attributes = p_attributes p.string_arr_emails = data.emails || [] + p.keyword_emails = data.emails || [] p.int_score = data.score p.date_lastEnriched = data.lastEnriched ? new Date(data.lastEnriched).toISOString() : null p.date_joinedAt = new Date(data.joinedAt).toISOString() p.date_createdAt = new Date(data.createdAt).toISOString() p.bool_manuallyCreated = data.manuallyCreated ? data.manuallyCreated : false - p.int_totalReach = data.totalReach p.int_numberOfOpenSourceContributions = data.numberOfOpenSourceContributions p.string_arr_activeOn = data.activeOn p.int_activityCount = data.activityCount @@ -694,20 +710,64 @@ export class MemberSyncService { p_identities.push({ string_platform: identity.platform, string_username: identity.username, + keyword_username: identity.username, }) } p.nested_identities = p_identities + const p_weakIdentities = [] + for (const identity of data.weakIdentities) { + p_weakIdentities.push({ + string_platform: identity.platform, + string_username: identity.username, + keyword_username: identity.username, + }) + } + p.nested_weakIdentities = p_weakIdentities + const p_contributions = [] + if (data.contributions) { + for (const contribution of data.contributions) { + p_contributions.push({ + uuid_id: contribution.id, + string_url: contribution.url, + string_summary: contribution.summary, + int_numberCommits: contribution.numberCommits, + date_lastCommitDate: new Date(contribution.lastCommitDate).toISOString(), + date_firstCommitDate: new Date(contribution.firstCommitDate).toISOString(), + }) + } + } + + const p_affiliations = [] + for (const affiliation of data.affiliations) { + p_affiliations.push({ + uuid_id: affiliation.id, + string_segmentId: affiliation.segmentId, + string_segmentSlug: affiliation.segmentSlug, + string_segmentName: affiliation.segmentName, + string_segmentParentName: affiliation.segmentParentName, + string_organizationId: affiliation.organizationId, + string_organizationName: affiliation.organizationName, + string_organizationLogo: affiliation.organizationLogo, + date_dateStart: affiliation.dateStart + ? new Date(affiliation.dateStart).toISOString() + : null, + date_dateEnd: affiliation.dateEnd ? new Date(affiliation.dateEnd).toISOString() : null, + }) + } + const p_organizations = [] for (const organization of data.organizations) { p_organizations.push({ uuid_id: organization.id, string_logo: organization.logo, + string_website: organization.website, string_displayName: organization.displayName, obj_memberOrganizations: { string_title: organization.memberOrganizations?.title || null, date_dateStart: organization.memberOrganizations?.dateStart || null, date_dateEnd: organization.memberOrganizations?.dateEnd || null, + string_source: organization.memberOrganizations?.source || null, }, }) } @@ -721,7 +781,31 @@ export class MemberSyncService { }) } + const p_notes = [] + for (const note of data.notes) { + p_notes.push({ + uuid_id: note.id, + string_body: note.body, + }) + } + + const p_tasks = [] + for (const task of data.tasks) { + p_tasks.push({ + uuid_id: task.id, + string_name: task.name, + string_body: task.body, + string_status: task.status, + date_dueDate: task.dueDate, + string_type: task.type, + }) + } + + p.nested_contributions = p_contributions + p.nested_affiliations = p_affiliations p.nested_tags = p_tags + p.nested_notes = p_notes + p.nested_tasks = p_tasks p.uuid_arr_toMergeIds = data.toMergeIds p.uuid_arr_noMergeIds = data.noMergeIds diff --git a/services/libs/opensearch/src/service/organization.sync.service.ts b/services/libs/opensearch/src/service/organization.sync.service.ts index 49ffabcf6a..8a737c8b8d 100644 --- a/services/libs/opensearch/src/service/organization.sync.service.ts +++ b/services/libs/opensearch/src/service/organization.sync.service.ts @@ -539,6 +539,10 @@ export class OrganizationSyncService { p.string_gicsSector = data.gicsSector p.obj_grossAdditionsByMonth = data.grossAdditionsByMonth p.obj_grossDeparturesByMonth = data.grossDeparturesByMonth + p.obj_naics = data.naics + p.string_ticker = data.ticker + p.string_arr_tags = data.tags + p.string_arr_manuallyChangedFields = data.manuallyChangedFields // identities const p_identities = [] @@ -546,11 +550,24 @@ export class OrganizationSyncService { p_identities.push({ string_platform: identity.platform, string_name: identity.name, + keyword_name: identity.name, string_url: identity.url, }) } p.nested_identities = p_identities + // weak identities + const p_weakIdentities = [] + for (const identity of data.weakIdentities) { + p_weakIdentities.push({ + string_platform: identity.platform, + string_name: identity.name, + keyword_name: identity.name, + string_url: identity.url, + }) + } + p.nested_weakIdentities = p_weakIdentities + // aggregate data p.date_joinedAt = data.joinedAt ? new Date(data.joinedAt).toISOString() : null p.date_lastActive = data.lastActive ? new Date(data.lastActive).toISOString() : null diff --git a/services/libs/sqs/src/config.ts b/services/libs/sqs/src/config.ts index 859f2f0254..062fec30f9 100644 --- a/services/libs/sqs/src/config.ts +++ b/services/libs/sqs/src/config.ts @@ -1,4 +1,5 @@ import { + CrowdQueue, ISqsQueueConfig, SqsFifoThroughputLimitType, SqsQueueDeduplicationType, @@ -6,7 +7,7 @@ import { } from './types' export const INTEGRATION_RUN_WORKER_QUEUE_SETTINGS: ISqsQueueConfig = { - name: 'integration-run-worker', + name: CrowdQueue.INTEGRATION_RUN_WORKER, type: SqsQueueType.FIFO, waitTimeSeconds: 20, // seconds visibilityTimeout: 30, // seconds @@ -17,7 +18,7 @@ export const INTEGRATION_RUN_WORKER_QUEUE_SETTINGS: ISqsQueueConfig = { } export const INTEGRATION_STREAM_WORKER_QUEUE_SETTINGS: ISqsQueueConfig = { - name: 'integration-stream-worker', + name: CrowdQueue.INTEGRATION_STREAM_WORKER, type: SqsQueueType.FIFO, waitTimeSeconds: 20, // seconds visibilityTimeout: 30, // seconds @@ -28,7 +29,7 @@ export const INTEGRATION_STREAM_WORKER_QUEUE_SETTINGS: ISqsQueueConfig = { } export const INTEGRATION_DATA_WORKER_QUEUE_SETTINGS: ISqsQueueConfig = { - name: 'integration-data-worker', + name: CrowdQueue.INTEGRATION_DATA_WORKER, type: SqsQueueType.FIFO, waitTimeSeconds: 20, // seconds visibilityTimeout: 30, // seconds @@ -39,7 +40,7 @@ export const INTEGRATION_DATA_WORKER_QUEUE_SETTINGS: ISqsQueueConfig = { } export const DATA_SINK_WORKER_QUEUE_SETTINGS: ISqsQueueConfig = { - name: 'data-sink-worker', + name: CrowdQueue.DATA_SINK_WORKER, type: SqsQueueType.FIFO, waitTimeSeconds: 20, // seconds visibilityTimeout: 30, // seconds @@ -50,7 +51,7 @@ export const DATA_SINK_WORKER_QUEUE_SETTINGS: ISqsQueueConfig = { } export const NODEJS_WORKER_QUEUE_SETTINGS: ISqsQueueConfig = { - name: 'nodejs-worker', + name: CrowdQueue.NODEJS_WORKER, type: SqsQueueType.FIFO, waitTimeSeconds: 20, // seconds visibilityTimeout: 30, // seconds @@ -61,7 +62,7 @@ export const NODEJS_WORKER_QUEUE_SETTINGS: ISqsQueueConfig = { } export const SEARCH_SYNC_WORKER_QUEUE_SETTINGS: ISqsQueueConfig = { - name: 'search-sync-worker', + name: CrowdQueue.SEARCH_SYNC_WORKER, type: SqsQueueType.FIFO, waitTimeSeconds: 20, // seconds visibilityTimeout: 30, // seconds @@ -72,7 +73,7 @@ export const SEARCH_SYNC_WORKER_QUEUE_SETTINGS: ISqsQueueConfig = { } export const INTEGRATION_SYNC_WORKER_QUEUE_SETTINGS: ISqsQueueConfig = { - name: 'integration-sync-worker', + name: CrowdQueue.INTEGRATION_SYNC_WORKER, type: SqsQueueType.FIFO, waitTimeSeconds: 20, // seconds visibilityTimeout: 30, // seconds diff --git a/services/libs/sqs/src/index.ts b/services/libs/sqs/src/index.ts index e61464d4e5..bd160a11da 100644 --- a/services/libs/sqs/src/index.ts +++ b/services/libs/sqs/src/index.ts @@ -2,4 +2,4 @@ export * from './types' export * from './client' export * from './queue' export * from './config' -export * from './instances' +export * from './prioritization' diff --git a/services/libs/sqs/src/instances/dataSinkWorker.ts b/services/libs/sqs/src/instances/dataSinkWorker.ts deleted file mode 100644 index ec84ba4c10..0000000000 --- a/services/libs/sqs/src/instances/dataSinkWorker.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { Logger } from '@crowd/logging' -import { DATA_SINK_WORKER_QUEUE_SETTINGS } from '../config' -import { SqsQueueEmitter } from '../queue' -import { SqsClient } from '../types' -import { - CreateAndProcessActivityResultQueueMessage, - IActivityData, - ProcessIntegrationResultQueueMessage, - CheckResultsQueueMessage, -} from '@crowd/types' -import { Tracer } from '@crowd/tracing' - -export class DataSinkWorkerEmitter extends SqsQueueEmitter { - constructor(client: SqsClient, tracer: Tracer, parentLog: Logger) { - super(client, DATA_SINK_WORKER_QUEUE_SETTINGS, tracer, parentLog) - } - - public async triggerResultProcessing( - tenantId: string, - platform: string, - resultId: string, - sourceId: string, - deduplicationId?: string, - ) { - await this.sendMessage( - sourceId, - new ProcessIntegrationResultQueueMessage(resultId), - deduplicationId || resultId, - ) - } - - public async createAndProcessActivityResult( - tenantId: string, - segmentId: string, - integrationId: string, - activity: IActivityData, - ) { - await this.sendMessage( - new Date().toISOString(), - new CreateAndProcessActivityResultQueueMessage(tenantId, segmentId, integrationId, activity), - ) - } - - public async checkResults() { - await this.sendMessage('global', new CheckResultsQueueMessage()) - } -} diff --git a/services/libs/sqs/src/instances/index.ts b/services/libs/sqs/src/instances/index.ts deleted file mode 100644 index d98d6b2ba5..0000000000 --- a/services/libs/sqs/src/instances/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -export * from './integrationRunWorker' -export * from './integrationStreamWorker' -export * from './integrationDataWorker' -export * from './dataSinkWorker' -export * from './nodejsWorker' -export * from './searchSyncWorker' -export * from './integrationSyncWorker' diff --git a/services/libs/sqs/src/instances/integrationDataWorker.ts b/services/libs/sqs/src/instances/integrationDataWorker.ts deleted file mode 100644 index 6607db7c7f..0000000000 --- a/services/libs/sqs/src/instances/integrationDataWorker.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Logger } from '@crowd/logging' -import { INTEGRATION_DATA_WORKER_QUEUE_SETTINGS } from '../config' -import { SqsQueueEmitter } from '../queue' -import { SqsClient } from '../types' -import { ProcessStreamDataQueueMessage } from '@crowd/types' -import { Tracer } from '@crowd/tracing' - -export class IntegrationDataWorkerEmitter extends SqsQueueEmitter { - constructor(client: SqsClient, tracer: Tracer, parentLog: Logger) { - super(client, INTEGRATION_DATA_WORKER_QUEUE_SETTINGS, tracer, parentLog) - } - - public async triggerDataProcessing(tenantId: string, platform: string, dataId: string) { - await this.sendMessage(dataId, new ProcessStreamDataQueueMessage(dataId), dataId) - } -} diff --git a/services/libs/sqs/src/instances/integrationRunWorker.ts b/services/libs/sqs/src/instances/integrationRunWorker.ts deleted file mode 100644 index a64e6c90a0..0000000000 --- a/services/libs/sqs/src/instances/integrationRunWorker.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { Logger } from '@crowd/logging' -import { INTEGRATION_RUN_WORKER_QUEUE_SETTINGS } from '../config' -import { SqsQueueEmitter } from '../queue' -import { SqsClient } from '../types' -import { - StreamProcessedQueueMessage, - GenerateRunStreamsQueueMessage, - StartIntegrationRunQueueMessage, - CheckRunsQueueMessage, -} from '@crowd/types' -import { Tracer } from '@crowd/tracing' - -export class IntegrationRunWorkerEmitter extends SqsQueueEmitter { - constructor(client: SqsClient, tracer: Tracer, parentLog: Logger) { - super(client, INTEGRATION_RUN_WORKER_QUEUE_SETTINGS, tracer, parentLog) - } - - public async checkRuns() { - await this.sendMessage('global', new CheckRunsQueueMessage()) - } - - public async triggerIntegrationRun( - tenantId: string, - platform: string, - integrationId: string, - onboarding: boolean, - isManualRun?: boolean, - manualSettings?: unknown, - ): Promise { - await this.sendMessage( - integrationId, - new StartIntegrationRunQueueMessage(integrationId, onboarding, isManualRun, manualSettings), - ) - } - - public async triggerRunProcessing( - tenantId: string, - platform: string, - runId: string, - isManualRun?: boolean, - manualSettings?: unknown, - ): Promise { - await this.sendMessage( - runId, - new GenerateRunStreamsQueueMessage(runId, isManualRun, manualSettings), - runId, - ) - } - - public async streamProcessed(tenantId: string, platform: string, runId: string): Promise { - await this.sendMessage(runId, new StreamProcessedQueueMessage(runId)) - } -} diff --git a/services/libs/sqs/src/instances/integrationStreamWorker.ts b/services/libs/sqs/src/instances/integrationStreamWorker.ts deleted file mode 100644 index 45cbc2a54d..0000000000 --- a/services/libs/sqs/src/instances/integrationStreamWorker.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { Logger } from '@crowd/logging' -import { INTEGRATION_STREAM_WORKER_QUEUE_SETTINGS } from '../config' -import { SqsQueueEmitter } from '../queue' -import { SqsClient } from '../types' -import { - CheckStreamsQueueMessage, - ContinueProcessingRunStreamsQueueMessage, - ProcessStreamQueueMessage, - ProcessWebhookStreamQueueMessage, -} from '@crowd/types' -import { generateUUIDv1 } from '@crowd/common' -import { Tracer } from '@crowd/tracing' - -export class IntegrationStreamWorkerEmitter extends SqsQueueEmitter { - constructor(client: SqsClient, tracer: Tracer, parentLog: Logger) { - super(client, INTEGRATION_STREAM_WORKER_QUEUE_SETTINGS, tracer, parentLog) - } - - public async checkStreams() { - await this.sendMessage('global', new CheckStreamsQueueMessage()) - } - - public async continueProcessingRunStreams( - tenantId: string, - platform: string, - runId: string, - ): Promise { - await this.sendMessage(runId, new ContinueProcessingRunStreamsQueueMessage(runId)) - } - - public async triggerStreamProcessing( - tenantId: string, - platform: string, - streamId: string, - ): Promise { - await this.sendMessage(generateUUIDv1(), new ProcessStreamQueueMessage(streamId)) - } - - public async triggerWebhookProcessing( - tenantId: string, - platform: string, - webhookId: string, - ): Promise { - await this.sendMessage(generateUUIDv1(), new ProcessWebhookStreamQueueMessage(webhookId)) - } -} diff --git a/services/libs/sqs/src/instances/nodejsWorker.ts b/services/libs/sqs/src/instances/nodejsWorker.ts deleted file mode 100644 index 744ddacbdd..0000000000 --- a/services/libs/sqs/src/instances/nodejsWorker.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { Logger } from '@crowd/logging' -import { NODEJS_WORKER_QUEUE_SETTINGS } from '../config' -import { SqsQueueEmitter } from '../queue' -import { SqsClient } from '../types' -import { - IQueueMessage, - NewActivityAutomationQueueMessage, - NewMemberAutomationQueueMessage, -} from '@crowd/types' -import { Tracer } from '@crowd/tracing' - -export class NodejsWorkerEmitter extends SqsQueueEmitter { - constructor(client: SqsClient, tracer: Tracer, parentLog: Logger) { - super(client, NODEJS_WORKER_QUEUE_SETTINGS, tracer, parentLog) - } - - public override sendMessage( - groupId: string, - message: IQueueMessage, - deduplicationId: string, - ): Promise { - return super.sendMessage(groupId, message, deduplicationId) - } - - public async processAutomationForNewActivity( - tenantId: string, - activityId: string, - segmentId: string, - ): Promise { - await this.sendMessage( - `${activityId}--${segmentId}`, - new NewActivityAutomationQueueMessage(tenantId, activityId, segmentId), - `${activityId}--${segmentId}`, - ) - } - - public async processAutomationForNewMember(tenantId: string, memberId: string): Promise { - await this.sendMessage( - memberId, - new NewMemberAutomationQueueMessage(tenantId, memberId), - memberId, - ) - } -} diff --git a/services/libs/sqs/src/prioritization.ts b/services/libs/sqs/src/prioritization.ts new file mode 100644 index 0000000000..10649dbe57 --- /dev/null +++ b/services/libs/sqs/src/prioritization.ts @@ -0,0 +1,179 @@ +import { groupBy } from '@crowd/common' +import { Logger, getChildLogger } from '@crowd/logging' +import { Tracer } from '@crowd/tracing' +import { IQueueMessage, ISqsQueueReceiver, QueuePriorityLevel } from '@crowd/types' +import { SqsQueueEmitter, SqsQueueReceiver } from './queue' +import { ISqsQueueConfig, SqsClient } from './types' + +export abstract class SqsPrioritizedQueueReciever { + protected readonly log: Logger + private readonly levelReceiver: ISqsQueueReceiver + private readonly defaultReceiver: ISqsQueueReceiver + + public constructor( + level: QueuePriorityLevel, + sqsClient: SqsClient, + queueConf: ISqsQueueConfig, + maxConcurrentMessageProcessing: number, + protected readonly tracer: Tracer, + parentLog: Logger, + deleteMessageImmediately = false, + visibilityTimeoutSeconds?: number, + receiveMessageCount?: number, + ) { + this.log = getChildLogger(this.constructor.name, parentLog, { + queueName: queueConf.name, + type: queueConf.type, + }) + + const processFunc = this.processMessage.bind(this) + + this.defaultReceiver = new (class extends SqsQueueReceiver { + constructor() { + super( + sqsClient, + queueConf, + maxConcurrentMessageProcessing, + tracer, + parentLog, + deleteMessageImmediately, + visibilityTimeoutSeconds, + receiveMessageCount, + ) + } + + public async processMessage(data: IQueueMessage, receiptHandle?: string): Promise { + return processFunc(data, receiptHandle) + } + })() + + const config = { ...queueConf, name: `${queueConf.name}-${level}` } + this.levelReceiver = new (class extends SqsQueueReceiver { + constructor() { + super( + sqsClient, + config, + maxConcurrentMessageProcessing, + tracer, + parentLog, + deleteMessageImmediately, + visibilityTimeoutSeconds, + receiveMessageCount, + ) + } + + public async processMessage(data: IQueueMessage, receiptHandle?: string): Promise { + return processFunc(data, receiptHandle) + } + })() + } + + public async start(): Promise { + await Promise.all([this.defaultReceiver.start(), this.levelReceiver.start()]) + } + + public stop(): void { + this.defaultReceiver.stop() + this.levelReceiver.stop() + } + + public abstract processMessage(data: IQueueMessage, receiptHandle?: string): Promise +} + +export class SqsPrioritizedQueueEmitter { + private readonly emittersMap: Map = new Map() + private readonly defaultEmitter: SqsQueueEmitter + + public constructor( + sqsClient: SqsClient, + queueConf: ISqsQueueConfig, + tracer: Tracer, + parentLog: Logger, + ) { + this.defaultEmitter = new SqsQueueEmitter(sqsClient, queueConf, tracer, parentLog) + for (const level of Object.values(QueuePriorityLevel)) { + const config = { ...queueConf, name: `${queueConf.name}-${level}` } + this.emittersMap.set(level, new SqsQueueEmitter(sqsClient, config, tracer, parentLog)) + } + } + + public isInitialized(): boolean { + const allInitialized = + Array.from(this.emittersMap.values()).find((e) => !e.isInitialized()) === undefined + + return allInitialized && this.defaultEmitter.isInitialized() + } + + public async init(): Promise { + await Promise.all( + Array.from(this.emittersMap.values()) + .map((e) => e.init()) + .concat(this.defaultEmitter.init()), + ) + } + + public async setMessageVisibilityTimeout( + receiptHandle: string, + newVisibility: number, + priorityLevel?: QueuePriorityLevel, + ): Promise { + if (priorityLevel) { + const emitter = this.emittersMap.get(priorityLevel) + if (!emitter) { + throw new Error(`Unknown priority level: ${priorityLevel}`) + } + return emitter.setMessageVisibilityTimeout(receiptHandle, newVisibility) + } else { + return this.defaultEmitter.setMessageVisibilityTimeout(receiptHandle, newVisibility) + } + } + + public async sendMessage( + groupId: string, + message: T, + deduplicationId?: string, + priorityLevel?: QueuePriorityLevel, + ): Promise { + if (priorityLevel) { + const emitter = this.emittersMap.get(priorityLevel) + if (!emitter) { + throw new Error(`Unknown priority level: ${priorityLevel}`) + } + return emitter.sendMessage(groupId, message, deduplicationId) + } else { + return this.defaultEmitter.sendMessage(groupId, message, deduplicationId) + } + } + + public async sendMessages( + messages: { + payload: T + groupId: string + deduplicationId?: string + id?: string + priorityLevel?: QueuePriorityLevel + }[], + ): Promise { + const grouped = groupBy( + messages.filter((m) => m.priorityLevel !== undefined), + (m) => m.priorityLevel, + ) + + for (const level of Array.from(grouped.keys()) as QueuePriorityLevel[]) { + const emitter = this.emittersMap.get(level) + if (!emitter) { + throw new Error(`Unknown priority level: ${level}`) + } + + const messages = grouped.get(level) || [] + if (messages.length > 0) { + await emitter.sendMessages(messages) + } + } + + const noPriorityLevel = messages.filter((m) => m.priorityLevel === undefined) + if (noPriorityLevel.length > 0) { + await this.defaultEmitter.sendMessages(noPriorityLevel) + } + } +} diff --git a/services/libs/sqs/src/queue.ts b/services/libs/sqs/src/queue.ts index b6c51016d4..20186d3aab 100644 --- a/services/libs/sqs/src/queue.ts +++ b/services/libs/sqs/src/queue.ts @@ -159,7 +159,10 @@ export abstract class SqsQueueReceiver extends SqsQueueBase { this.removeJob() }) // if error is detected don't delete the message from the queue - .catch(() => this.removeJob()) + .catch((err) => { + this.log.error(err, 'Error processing message!') + this.removeJob() + }) if (this.deleteMessageImmediately) { await this.deleteMessage(message.ReceiptHandle) @@ -214,7 +217,7 @@ export abstract class SqsQueueReceiver extends SqsQueueBase { } } -export abstract class SqsQueueEmitter extends SqsQueueBase implements ISqsQueueEmitter { +export class SqsQueueEmitter extends SqsQueueBase implements ISqsQueueEmitter { constructor(sqsClient: SqsClient, queueConf: ISqsQueueConfig, tracer: Tracer, parentLog: Logger) { super(sqsClient, queueConf, tracer, parentLog) } diff --git a/services/libs/sqs/src/types.ts b/services/libs/sqs/src/types.ts index 795ab1f57a..5afb3b1625 100644 --- a/services/libs/sqs/src/types.ts +++ b/services/libs/sqs/src/types.ts @@ -39,6 +39,16 @@ export enum SqsFifoThroughputLimitType { PER_MESSAGE_GROUP_ID = 'perMessageGroupId', } +export enum CrowdQueue { + INTEGRATION_RUN_WORKER = 'integration-run-worker', + INTEGRATION_STREAM_WORKER = 'integration-stream-worker', + INTEGRATION_DATA_WORKER = 'integration-data-worker', + DATA_SINK_WORKER = 'data-sink-worker', + NODEJS_WORKER = 'nodejs-worker', + SEARCH_SYNC_WORKER = 'search-sync-worker', + INTEGRATION_SYNC_WORKER = 'integration-sync-worker', +} + export interface ISqsQueueConfig { name: string type: SqsQueueType diff --git a/services/libs/telemetry/package-lock.json b/services/libs/telemetry/package-lock.json new file mode 100644 index 0000000000..17dd06166d --- /dev/null +++ b/services/libs/telemetry/package-lock.json @@ -0,0 +1,3776 @@ +{ + "name": "@crowd/telemetry", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "@crowd/telemetry", + "version": "1.0.0", + "dependencies": { + "@crowd/logging": "file:../logging", + "dd-trace": "^4.20.0" + }, + "devDependencies": { + "@types/node": "^18.16.3", + "@typescript-eslint/eslint-plugin": "^5.59.2", + "@typescript-eslint/parser": "^5.59.2", + "eslint": "^8.39.0", + "eslint-config-prettier": "^8.8.0", + "eslint-plugin-prettier": "^4.2.1", + "prettier": "^2.8.8", + "typescript": "^5.0.4" + } + }, + "../common": { + "name": "@crowd/common", + "version": "1.0.0", + "extraneous": true, + "dependencies": { + "@crowd/logging": "file:../logging", + "@crowd/types": "file:../types", + "lodash.get": "~4.4.2", + "psl": "^1.9.0", + "uuid": "^9.0.0" + }, + "devDependencies": { + "@types/node": "^18.16.3", + "@typescript-eslint/eslint-plugin": "^5.59.2", + "@typescript-eslint/parser": "^5.59.2", + "eslint": "^8.39.0", + "eslint-config-prettier": "^8.8.0", + "eslint-plugin-prettier": "^4.2.1", + "prettier": "^2.8.8", + "typescript": "^5.0.4" + } + }, + "../logging": { + "name": "@crowd/logging", + "version": "1.0.0", + "dependencies": { + "@crowd/common": "file:../common", + "@crowd/tracing": "file:../tracing", + "bunyan": "^1.8.15", + "bunyan-format": "^0.2.1" + }, + "devDependencies": { + "@types/bunyan": "^1.8.8", + "@types/bunyan-format": "^0.2.5", + "@types/node": "^18.16.3", + "@typescript-eslint/eslint-plugin": "^5.59.2", + "@typescript-eslint/parser": "^5.59.2", + "eslint": "^8.39.0", + "eslint-config-prettier": "^8.8.0", + "eslint-plugin-prettier": "^4.2.1", + "prettier": "^2.8.8", + "typescript": "^5.0.4" + } + }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@crowd/logging": { + "resolved": "../logging", + "link": true + }, + "node_modules/@datadog/native-appsec": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@datadog/native-appsec/-/native-appsec-4.0.0.tgz", + "integrity": "sha512-myTguXJ3VQHS2E1ylNsSF1avNpDmq5t+K4Q47wdzeakGc3sDIDDyEbvuFTujl9c9wBIkup94O1mZj5DR37ajzA==", + "hasInstallScript": true, + "dependencies": { + "node-gyp-build": "^3.9.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@datadog/native-iast-rewriter": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@datadog/native-iast-rewriter/-/native-iast-rewriter-2.2.1.tgz", + "integrity": "sha512-DyZlE8gNa5AoOFNKGRJU4RYF/Y/tJzv4bIAMuVBbEnMA0xhiIYqpYQG8T3OKkALl3VSEeBMjYwuOR2fCrJ6gzA==", + "dependencies": { + "lru-cache": "^7.14.0", + "node-gyp-build": "^4.5.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@datadog/native-iast-rewriter/node_modules/node-gyp-build": { + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.7.1.tgz", + "integrity": "sha512-wTSrZ+8lsRRa3I3H8Xr65dLWSgCvY2l4AOnaeKdPA9TB/WYMPaTcrzf3rXvFoVvjKNVnu0CcWSx54qq9GKRUYg==", + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/@datadog/native-iast-taint-tracking": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/@datadog/native-iast-taint-tracking/-/native-iast-taint-tracking-1.6.4.tgz", + "integrity": "sha512-Owxk7hQ4Dxwv4zJAoMjRga0IvE6lhvxnNc8pJCHsemCWBXchjr/9bqg05Zy5JnMbKUWn4XuZeJD6RFZpRa8bfw==", + "hasInstallScript": true, + "dependencies": { + "node-gyp-build": "^3.9.0" + } + }, + "node_modules/@datadog/native-metrics": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@datadog/native-metrics/-/native-metrics-2.0.0.tgz", + "integrity": "sha512-YklGVwUtmKGYqFf1MNZuOHvTYdKuR4+Af1XkWcMD8BwOAjxmd9Z+97328rCOY8TFUJzlGUPaXzB8j2qgG/BMwA==", + "hasInstallScript": true, + "dependencies": { + "node-addon-api": "^6.1.0", + "node-gyp-build": "^3.9.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@datadog/pprof": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@datadog/pprof/-/pprof-4.0.1.tgz", + "integrity": "sha512-TavqyiyQZOaUM9eQB07r8+K/T1CqKyOdsUGxpN79+BF+eOQBpTj/Cte6KdlhcUSKL3h5hSjC+vlgA7uW2qtVhA==", + "hasInstallScript": true, + "dependencies": { + "delay": "^5.0.0", + "node-gyp-build": "<4.0", + "p-limit": "^3.1.0", + "pprof-format": "^2.0.7", + "source-map": "^0.7.4" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@datadog/sketches-js": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@datadog/sketches-js/-/sketches-js-2.1.0.tgz", + "integrity": "sha512-smLocSfrt3s53H/XSVP3/1kP42oqvrkjUPtyaFd1F79ux24oE31BKt+q0c6lsa6hOYrFzsIwyc5GXAI5JmfOew==" + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.3.tgz", + "integrity": "sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.54.0.tgz", + "integrity": "sha512-ut5V+D+fOoWPgGGNj83GGjnntO39xDy6DWxO0wb7Jp3DcMX0TfIqdzHF85VTQkerdyGmuuMD9AKAo5KiNlf/AQ==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", + "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", + "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", + "dev": true + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@opentelemetry/api": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.7.0.tgz", + "integrity": "sha512-AdY5wvN0P2vXBi3b29hxZgSFvdhdxPB9+f0B6s//P9Q8nibRWeA3cHm8UmLpio9ABigkVHJ5NMPk+Mz8VCCyrw==", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@opentelemetry/core": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.18.1.tgz", + "integrity": "sha512-kvnUqezHMhsQvdsnhnqTNfAJs3ox/isB0SVrM1dhVFw7SsB7TstuVa6fgWnN2GdPyilIFLUvvbTZoVRmx6eiRg==", + "dependencies": { + "@opentelemetry/semantic-conventions": "1.18.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.8.0" + } + }, + "node_modules/@opentelemetry/semantic-conventions": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.18.1.tgz", + "integrity": "sha512-+NLGHr6VZwcgE/2lw8zDIufOCGnzsA5CbQIMleXZTrgkBd0TanCX+MiDYJ1TOS4KL/Tqk0nFRxawnaYr6pkZkA==", + "engines": { + "node": ">=14" + } + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, + "node_modules/@types/node": { + "version": "18.18.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.18.13.tgz", + "integrity": "sha512-vXYZGRrSCreZmq1rEjMRLXJhiy8MrIeVasx+PCVlP414N7CJLHnMf+juVvjdprHyH+XRy3zKZLHeNueOpJCn0g==", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/semver": { + "version": "7.5.6", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", + "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", + "dev": true + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", + "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/type-utils": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", + "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", + "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "node_modules/acorn": { + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-assertions": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", + "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", + "peerDependencies": { + "acorn": "^8" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "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": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", + "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==" + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypto-randomuuid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/crypto-randomuuid/-/crypto-randomuuid-1.0.0.tgz", + "integrity": "sha512-/RC5F4l1SCqD/jazwUF6+t34Cd8zTSAGZ7rvvZu1whZUhD2a5MOGKjSGowoGcpj/cbVZk1ZODIooJEQQq3nNAA==" + }, + "node_modules/dc-polyfill": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/dc-polyfill/-/dc-polyfill-0.1.3.tgz", + "integrity": "sha512-Wyk5n/5KUj3GfVKV2jtDbtChC/Ff9fjKsBcg4ZtYW1yQe3DXNHcGURvmoxhqQdfOQ9TwyMjnfyv1lyYcOkFkFA==", + "engines": { + "node": ">=12.17" + } + }, + "node_modules/dd-trace": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/dd-trace/-/dd-trace-4.20.0.tgz", + "integrity": "sha512-y7IDLSSt6nww6zMdw/I8oLdfgOQADIOkERCNdfSzlBrXHz5CHimEOFfsHN87ag0mn6vusr06aoi+CQRZSNJz2g==", + "hasInstallScript": true, + "dependencies": { + "@datadog/native-appsec": "4.0.0", + "@datadog/native-iast-rewriter": "2.2.1", + "@datadog/native-iast-taint-tracking": "1.6.4", + "@datadog/native-metrics": "^2.0.0", + "@datadog/pprof": "4.0.1", + "@datadog/sketches-js": "^2.1.0", + "@opentelemetry/api": "^1.0.0", + "@opentelemetry/core": "^1.14.0", + "crypto-randomuuid": "^1.0.0", + "dc-polyfill": "^0.1.2", + "ignore": "^5.2.4", + "import-in-the-middle": "^1.4.2", + "int64-buffer": "^0.1.9", + "ipaddr.js": "^2.1.0", + "istanbul-lib-coverage": "3.2.0", + "jest-docblock": "^29.7.0", + "koalas": "^1.0.2", + "limiter": "^1.1.4", + "lodash.kebabcase": "^4.1.1", + "lodash.pick": "^4.4.0", + "lodash.sortby": "^4.7.0", + "lodash.uniq": "^4.5.0", + "lru-cache": "^7.14.0", + "methods": "^1.1.2", + "module-details-from-path": "^1.0.3", + "msgpack-lite": "^0.1.26", + "node-abort-controller": "^3.1.1", + "opentracing": ">=0.12.1", + "path-to-regexp": "^0.1.2", + "pprof-format": "^2.0.7", + "protobufjs": "^7.2.4", + "retry": "^0.13.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/delay": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/delay/-/delay-5.0.0.tgz", + "integrity": "sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.54.0.tgz", + "integrity": "sha512-NY0DfAkM8BIZDVl6PgSa1ttZbx3xHgJzSNJKYcQglem6CppHyMhRIQkBVSSMaSRnLhig3jsDbEzOjwCVt4AmmA==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.3", + "@eslint/js": "8.54.0", + "@humanwhocodes/config-array": "^0.11.13", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-prettier": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz", + "integrity": "sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", + "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==", + "dev": true, + "dependencies": { + "prettier-linter-helpers": "^1.0.0" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "eslint": ">=7.28.0", + "prettier": ">=2.0.0" + }, + "peerDependenciesMeta": { + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/event-lite": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/event-lite/-/event-lite-0.1.3.tgz", + "integrity": "sha512-8qz9nOz5VeD2z96elrEKD2U433+L3DWdUdDkOINLGOJvx1GsMBbMn0aCeu28y8/e85A6mCigBiFlYMnTBEGlSw==" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", + "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", + "dev": true + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "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/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/ignore": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", + "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-in-the-middle": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.4.2.tgz", + "integrity": "sha512-9WOz1Yh/cvO/p69sxRmhyQwrIGGSp7EIdcb+fFNVi7CzQGQB8U1/1XrKVSbEd/GNOAeM0peJtmi7+qphe7NvAw==", + "dependencies": { + "acorn": "^8.8.2", + "acorn-import-assertions": "^1.9.0", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/int64-buffer": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/int64-buffer/-/int64-buffer-0.1.10.tgz", + "integrity": "sha512-v7cSY1J8ydZ0GyjUHqF+1bshJ6cnEVLo9EnjB8p+4HDRPZc9N5jjmvUV7NvEsqQOKyH0pmIBFWXVQbiS0+OBbA==" + }, + "node_modules/ipaddr.js": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.1.0.tgz", + "integrity": "sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/koalas": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/koalas/-/koalas-1.0.2.tgz", + "integrity": "sha512-RYhBbYaTTTHId3l6fnMZc3eGQNW6FVCqMG6AMwA5I1Mafr6AflaXeoi6x3xQuATRotGYRLk6+1ELZH4dstFNOA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/limiter": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.5.tgz", + "integrity": "sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA==" + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.kebabcase": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", + "integrity": "sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/lodash.pick": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", + "integrity": "sha512-hXt6Ul/5yWjfklSGvLQl8vM//l3FtyHZeuelpzK6mm99pNvN9yTDruNZPEJZD1oWrqo+izBmB7oUfWgcCX7s4Q==" + }, + "node_modules/lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==" + }, + "node_modules/lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==" + }, + "node_modules/long": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" + }, + "node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/module-details-from-path": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.3.tgz", + "integrity": "sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==" + }, + "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/msgpack-lite": { + "version": "0.1.26", + "resolved": "https://registry.npmjs.org/msgpack-lite/-/msgpack-lite-0.1.26.tgz", + "integrity": "sha512-SZ2IxeqZ1oRFGo0xFGbvBJWMp3yLIY9rlIJyxy8CGrwZn1f0ZK4r6jV/AM1r0FZMDUkWkglOk/eeKIL9g77Nxw==", + "dependencies": { + "event-lite": "^0.1.1", + "ieee754": "^1.1.8", + "int64-buffer": "^0.1.9", + "isarray": "^1.0.0" + }, + "bin": { + "msgpack": "bin/msgpack" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, + "node_modules/node-abort-controller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", + "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==" + }, + "node_modules/node-addon-api": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", + "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==" + }, + "node_modules/node-gyp-build": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-3.9.0.tgz", + "integrity": "sha512-zLcTg6P4AbcHPq465ZMFNXx7XpKKJh+7kkN699NiQWisR2uWYOWNWqRHAmbnmKiL4e9aLSlmy5U7rEMUXV59+A==", + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/opentracing": { + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/opentracing/-/opentracing-0.14.7.tgz", + "integrity": "sha512-vz9iS7MJ5+Bp1URw8Khvdyw1H/hGvzHWlKQ7eRrQojSCDL1/SrWfrY9QebLw97n2deyRtzHRC3MkQfVNUCo91Q==", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pprof-format": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/pprof-format/-/pprof-format-2.0.7.tgz", + "integrity": "sha512-1qWaGAzwMpaXJP9opRa23nPnt2Egi7RMNoNBptEE/XwHbcn4fC2b/4U4bKc5arkGkIh2ZabpF2bEb+c5GNHEKA==" + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/protobufjs": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.5.tgz", + "integrity": "sha512-gGXRSXvxQ7UiPgfw8gevrfRWcTlSbOFg+p/N+JVJEK5VhueL2miT6qTymqAmjr1Q5WbOCyJbyrk6JfWKwlFn6A==", + "hasInstallScript": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/strip-ansi": { + "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": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.2.tgz", + "integrity": "sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + }, + "dependencies": { + "@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true + }, + "@crowd/logging": { + "version": "file:../logging", + "requires": { + "@crowd/common": "file:../common", + "@crowd/tracing": "file:../tracing", + "@types/bunyan": "^1.8.8", + "@types/bunyan-format": "^0.2.5", + "@types/node": "^18.16.3", + "@typescript-eslint/eslint-plugin": "^5.59.2", + "@typescript-eslint/parser": "^5.59.2", + "bunyan": "^1.8.15", + "bunyan-format": "^0.2.1", + "eslint": "^8.39.0", + "eslint-config-prettier": "^8.8.0", + "eslint-plugin-prettier": "^4.2.1", + "prettier": "^2.8.8", + "typescript": "^5.0.4" + } + }, + "@datadog/native-appsec": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@datadog/native-appsec/-/native-appsec-4.0.0.tgz", + "integrity": "sha512-myTguXJ3VQHS2E1ylNsSF1avNpDmq5t+K4Q47wdzeakGc3sDIDDyEbvuFTujl9c9wBIkup94O1mZj5DR37ajzA==", + "requires": { + "node-gyp-build": "^3.9.0" + } + }, + "@datadog/native-iast-rewriter": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@datadog/native-iast-rewriter/-/native-iast-rewriter-2.2.1.tgz", + "integrity": "sha512-DyZlE8gNa5AoOFNKGRJU4RYF/Y/tJzv4bIAMuVBbEnMA0xhiIYqpYQG8T3OKkALl3VSEeBMjYwuOR2fCrJ6gzA==", + "requires": { + "lru-cache": "^7.14.0", + "node-gyp-build": "^4.5.0" + }, + "dependencies": { + "node-gyp-build": { + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.7.1.tgz", + "integrity": "sha512-wTSrZ+8lsRRa3I3H8Xr65dLWSgCvY2l4AOnaeKdPA9TB/WYMPaTcrzf3rXvFoVvjKNVnu0CcWSx54qq9GKRUYg==" + } + } + }, + "@datadog/native-iast-taint-tracking": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/@datadog/native-iast-taint-tracking/-/native-iast-taint-tracking-1.6.4.tgz", + "integrity": "sha512-Owxk7hQ4Dxwv4zJAoMjRga0IvE6lhvxnNc8pJCHsemCWBXchjr/9bqg05Zy5JnMbKUWn4XuZeJD6RFZpRa8bfw==", + "requires": { + "node-gyp-build": "^3.9.0" + } + }, + "@datadog/native-metrics": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@datadog/native-metrics/-/native-metrics-2.0.0.tgz", + "integrity": "sha512-YklGVwUtmKGYqFf1MNZuOHvTYdKuR4+Af1XkWcMD8BwOAjxmd9Z+97328rCOY8TFUJzlGUPaXzB8j2qgG/BMwA==", + "requires": { + "node-addon-api": "^6.1.0", + "node-gyp-build": "^3.9.0" + } + }, + "@datadog/pprof": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@datadog/pprof/-/pprof-4.0.1.tgz", + "integrity": "sha512-TavqyiyQZOaUM9eQB07r8+K/T1CqKyOdsUGxpN79+BF+eOQBpTj/Cte6KdlhcUSKL3h5hSjC+vlgA7uW2qtVhA==", + "requires": { + "delay": "^5.0.0", + "node-gyp-build": "<4.0", + "p-limit": "^3.1.0", + "pprof-format": "^2.0.7", + "source-map": "^0.7.4" + } + }, + "@datadog/sketches-js": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@datadog/sketches-js/-/sketches-js-2.1.0.tgz", + "integrity": "sha512-smLocSfrt3s53H/XSVP3/1kP42oqvrkjUPtyaFd1F79ux24oE31BKt+q0c6lsa6hOYrFzsIwyc5GXAI5JmfOew==" + }, + "@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^3.3.0" + } + }, + "@eslint-community/regexpp": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "dev": true + }, + "@eslint/eslintrc": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.3.tgz", + "integrity": "sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + } + }, + "@eslint/js": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.54.0.tgz", + "integrity": "sha512-ut5V+D+fOoWPgGGNj83GGjnntO39xDy6DWxO0wb7Jp3DcMX0TfIqdzHF85VTQkerdyGmuuMD9AKAo5KiNlf/AQ==", + "dev": true + }, + "@humanwhocodes/config-array": { + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", + "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", + "dev": true, + "requires": { + "@humanwhocodes/object-schema": "^2.0.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + } + }, + "@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true + }, + "@humanwhocodes/object-schema": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", + "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", + "dev": true + }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, + "@opentelemetry/api": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.7.0.tgz", + "integrity": "sha512-AdY5wvN0P2vXBi3b29hxZgSFvdhdxPB9+f0B6s//P9Q8nibRWeA3cHm8UmLpio9ABigkVHJ5NMPk+Mz8VCCyrw==" + }, + "@opentelemetry/core": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.18.1.tgz", + "integrity": "sha512-kvnUqezHMhsQvdsnhnqTNfAJs3ox/isB0SVrM1dhVFw7SsB7TstuVa6fgWnN2GdPyilIFLUvvbTZoVRmx6eiRg==", + "requires": { + "@opentelemetry/semantic-conventions": "1.18.1" + } + }, + "@opentelemetry/semantic-conventions": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.18.1.tgz", + "integrity": "sha512-+NLGHr6VZwcgE/2lw8zDIufOCGnzsA5CbQIMleXZTrgkBd0TanCX+MiDYJ1TOS4KL/Tqk0nFRxawnaYr6pkZkA==" + }, + "@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" + }, + "@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" + }, + "@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "requires": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" + }, + "@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" + }, + "@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" + }, + "@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" + }, + "@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" + }, + "@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, + "@types/node": { + "version": "18.18.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.18.13.tgz", + "integrity": "sha512-vXYZGRrSCreZmq1rEjMRLXJhiy8MrIeVasx+PCVlP414N7CJLHnMf+juVvjdprHyH+XRy3zKZLHeNueOpJCn0g==", + "requires": { + "undici-types": "~5.26.4" + } + }, + "@types/semver": { + "version": "7.5.6", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", + "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", + "dev": true + }, + "@typescript-eslint/eslint-plugin": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", + "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", + "dev": true, + "requires": { + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/type-utils": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/parser": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", + "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "debug": "^4.3.4" + } + }, + "@typescript-eslint/scope-manager": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" + } + }, + "@typescript-eslint/type-utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", + "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", + "dev": true, + "requires": { + "@typescript-eslint/typescript-estree": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + } + }, + "@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "acorn": { + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==" + }, + "acorn-import-assertions": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", + "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", + "requires": {} + }, + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "requires": {} + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "cjs-module-lexer": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", + "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==" + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "crypto-randomuuid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/crypto-randomuuid/-/crypto-randomuuid-1.0.0.tgz", + "integrity": "sha512-/RC5F4l1SCqD/jazwUF6+t34Cd8zTSAGZ7rvvZu1whZUhD2a5MOGKjSGowoGcpj/cbVZk1ZODIooJEQQq3nNAA==" + }, + "dc-polyfill": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/dc-polyfill/-/dc-polyfill-0.1.3.tgz", + "integrity": "sha512-Wyk5n/5KUj3GfVKV2jtDbtChC/Ff9fjKsBcg4ZtYW1yQe3DXNHcGURvmoxhqQdfOQ9TwyMjnfyv1lyYcOkFkFA==" + }, + "dd-trace": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/dd-trace/-/dd-trace-4.20.0.tgz", + "integrity": "sha512-y7IDLSSt6nww6zMdw/I8oLdfgOQADIOkERCNdfSzlBrXHz5CHimEOFfsHN87ag0mn6vusr06aoi+CQRZSNJz2g==", + "requires": { + "@datadog/native-appsec": "4.0.0", + "@datadog/native-iast-rewriter": "2.2.1", + "@datadog/native-iast-taint-tracking": "1.6.4", + "@datadog/native-metrics": "^2.0.0", + "@datadog/pprof": "4.0.1", + "@datadog/sketches-js": "^2.1.0", + "@opentelemetry/api": "^1.0.0", + "@opentelemetry/core": "^1.14.0", + "crypto-randomuuid": "^1.0.0", + "dc-polyfill": "^0.1.2", + "ignore": "^5.2.4", + "import-in-the-middle": "^1.4.2", + "int64-buffer": "^0.1.9", + "ipaddr.js": "^2.1.0", + "istanbul-lib-coverage": "3.2.0", + "jest-docblock": "^29.7.0", + "koalas": "^1.0.2", + "limiter": "^1.1.4", + "lodash.kebabcase": "^4.1.1", + "lodash.pick": "^4.4.0", + "lodash.sortby": "^4.7.0", + "lodash.uniq": "^4.5.0", + "lru-cache": "^7.14.0", + "methods": "^1.1.2", + "module-details-from-path": "^1.0.3", + "msgpack-lite": "^0.1.26", + "node-abort-controller": "^3.1.1", + "opentracing": ">=0.12.1", + "path-to-regexp": "^0.1.2", + "pprof-format": "^2.0.7", + "protobufjs": "^7.2.4", + "retry": "^0.13.1", + "semver": "^7.5.4" + } + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "delay": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/delay/-/delay-5.0.0.tgz", + "integrity": "sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==" + }, + "detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==" + }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + } + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "eslint": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.54.0.tgz", + "integrity": "sha512-NY0DfAkM8BIZDVl6PgSa1ttZbx3xHgJzSNJKYcQglem6CppHyMhRIQkBVSSMaSRnLhig3jsDbEzOjwCVt4AmmA==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.3", + "@eslint/js": "8.54.0", + "@humanwhocodes/config-array": "^0.11.13", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "dependencies": { + "eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, + "eslint-config-prettier": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz", + "integrity": "sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg==", + "dev": true, + "requires": {} + }, + "eslint-plugin-prettier": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", + "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==", + "dev": true, + "requires": { + "prettier-linter-helpers": "^1.0.0" + } + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true + }, + "espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "requires": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + } + }, + "esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "event-lite": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/event-lite/-/event-lite-0.1.3.tgz", + "integrity": "sha512-8qz9nOz5VeD2z96elrEKD2U433+L3DWdUdDkOINLGOJvx1GsMBbMn0aCeu28y8/e85A6mCigBiFlYMnTBEGlSw==" + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true + }, + "fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "dependencies": { + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + } + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "requires": { + "flat-cache": "^3.0.4" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "requires": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + } + }, + "flatted": { + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", + "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "requires": { + "is-glob": "^4.0.3" + } + }, + "globals": { + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + }, + "globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + } + }, + "graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "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 + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + }, + "ignore": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", + "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==" + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "import-in-the-middle": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.4.2.tgz", + "integrity": "sha512-9WOz1Yh/cvO/p69sxRmhyQwrIGGSp7EIdcb+fFNVi7CzQGQB8U1/1XrKVSbEd/GNOAeM0peJtmi7+qphe7NvAw==", + "requires": { + "acorn": "^8.8.2", + "acorn-import-assertions": "^1.9.0", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "int64-buffer": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/int64-buffer/-/int64-buffer-0.1.10.tgz", + "integrity": "sha512-v7cSY1J8ydZ0GyjUHqF+1bshJ6cnEVLo9EnjB8p+4HDRPZc9N5jjmvUV7NvEsqQOKyH0pmIBFWXVQbiS0+OBbA==" + }, + "ipaddr.js": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.1.0.tgz", + "integrity": "sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ==" + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==" + }, + "jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "requires": { + "detect-newline": "^3.0.0" + } + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "requires": { + "json-buffer": "3.0.1" + } + }, + "koalas": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/koalas/-/koalas-1.0.2.tgz", + "integrity": "sha512-RYhBbYaTTTHId3l6fnMZc3eGQNW6FVCqMG6AMwA5I1Mafr6AflaXeoi6x3xQuATRotGYRLk6+1ELZH4dstFNOA==" + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "limiter": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.5.tgz", + "integrity": "sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA==" + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "lodash.kebabcase": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", + "integrity": "sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==" + }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "lodash.pick": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", + "integrity": "sha512-hXt6Ul/5yWjfklSGvLQl8vM//l3FtyHZeuelpzK6mm99pNvN9yTDruNZPEJZD1oWrqo+izBmB7oUfWgcCX7s4Q==" + }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==" + }, + "lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==" + }, + "long": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" + }, + "lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==" + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" + }, + "micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "requires": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "module-details-from-path": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.3.tgz", + "integrity": "sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==" + }, + "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 + }, + "msgpack-lite": { + "version": "0.1.26", + "resolved": "https://registry.npmjs.org/msgpack-lite/-/msgpack-lite-0.1.26.tgz", + "integrity": "sha512-SZ2IxeqZ1oRFGo0xFGbvBJWMp3yLIY9rlIJyxy8CGrwZn1f0ZK4r6jV/AM1r0FZMDUkWkglOk/eeKIL9g77Nxw==", + "requires": { + "event-lite": "^0.1.1", + "ieee754": "^1.1.8", + "int64-buffer": "^0.1.9", + "isarray": "^1.0.0" + } + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, + "node-abort-controller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", + "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==" + }, + "node-addon-api": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", + "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==" + }, + "node-gyp-build": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-3.9.0.tgz", + "integrity": "sha512-zLcTg6P4AbcHPq465ZMFNXx7XpKKJh+7kkN699NiQWisR2uWYOWNWqRHAmbnmKiL4e9aLSlmy5U7rEMUXV59+A==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "opentracing": { + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/opentracing/-/opentracing-0.14.7.tgz", + "integrity": "sha512-vz9iS7MJ5+Bp1URw8Khvdyw1H/hGvzHWlKQ7eRrQojSCDL1/SrWfrY9QebLw97n2deyRtzHRC3MkQfVNUCo91Q==" + }, + "optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "requires": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + } + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true + }, + "pprof-format": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/pprof-format/-/pprof-format-2.0.7.tgz", + "integrity": "sha512-1qWaGAzwMpaXJP9opRa23nPnt2Egi7RMNoNBptEE/XwHbcn4fC2b/4U4bKc5arkGkIh2ZabpF2bEb+c5GNHEKA==" + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, + "prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "dev": true + }, + "prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "requires": { + "fast-diff": "^1.1.2" + } + }, + "protobufjs": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.5.tgz", + "integrity": "sha512-gGXRSXvxQ7UiPgfw8gevrfRWcTlSbOFg+p/N+JVJEK5VhueL2miT6qTymqAmjr1Q5WbOCyJbyrk6JfWKwlFn6A==", + "requires": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + } + }, + "punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true + }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==" + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" + } + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "requires": { + "lru-cache": "^6.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + } + } + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==" + }, + "strip-ansi": { + "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": "^5.0.1" + } + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + }, + "typescript": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.2.tgz", + "integrity": "sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ==", + "dev": true + }, + "undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==" + } + } +} diff --git a/services/libs/types/package-lock.json b/services/libs/types/package-lock.json new file mode 100644 index 0000000000..7a0b4472f3 --- /dev/null +++ b/services/libs/types/package-lock.json @@ -0,0 +1,3047 @@ +{ + "name": "@crowd/types", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "@crowd/types", + "version": "1.0.0", + "dependencies": { + "peopledatalabs": "~6.1.5" + }, + "devDependencies": { + "@types/node": "^18.16.3", + "@typescript-eslint/eslint-plugin": "^5.59.2", + "@typescript-eslint/parser": "^5.59.2", + "eslint": "^8.39.0", + "eslint-config-prettier": "^8.8.0", + "eslint-plugin-prettier": "^4.2.1", + "prettier": "^2.8.8", + "typescript": "^5.0.4" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", + "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz", + "integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.5.2", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "8.40.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.40.0.tgz", + "integrity": "sha512-ElyB54bJIhXQYVKjDSvCkPO1iU1tSAeVQJbllWJq1XQSmmA4dgFk8CbiBGpiOPxleE48vDogxCtmMYku4HSVLA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", + "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", + "dev": true + }, + "node_modules/@types/node": { + "version": "18.16.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.9.tgz", + "integrity": "sha512-IeB32oIV4oGArLrd7znD2rkHQ6EDCM+2Sr76dJnrHwv9OHBTTM6nuDLK9bmikXzPa0ZlWMWtRGo/Uw4mrzQedA==", + "dev": true + }, + "node_modules/@types/semver": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", + "dev": true + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.5.tgz", + "integrity": "sha512-feA9xbVRWJZor+AnLNAr7A8JRWeZqHUf4T9tlP+TN04b05pFVhO5eN7/O93Y/1OUlLMHKbnJisgDURs/qvtqdg==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.59.5", + "@typescript-eslint/type-utils": "5.59.5", + "@typescript-eslint/utils": "5.59.5", + "debug": "^4.3.4", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.5.tgz", + "integrity": "sha512-NJXQC4MRnF9N9yWqQE2/KLRSOLvrrlZb48NGVfBa+RuPMN6B7ZcK5jZOvhuygv4D64fRKnZI4L4p8+M+rfeQuw==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "5.59.5", + "@typescript-eslint/types": "5.59.5", + "@typescript-eslint/typescript-estree": "5.59.5", + "debug": "^4.3.4" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.5.tgz", + "integrity": "sha512-jVecWwnkX6ZgutF+DovbBJirZcAxgxC0EOHYt/niMROf8p4PwxxG32Qdhj/iIQQIuOflLjNkxoXyArkcIP7C3A==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.59.5", + "@typescript-eslint/visitor-keys": "5.59.5" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.5.tgz", + "integrity": "sha512-4eyhS7oGym67/pSxA2mmNq7X164oqDYNnZCUayBwJZIRVvKpBCMBzFnFxjeoDeShjtO6RQBHBuwybuX3POnDqg==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "5.59.5", + "@typescript-eslint/utils": "5.59.5", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.5.tgz", + "integrity": "sha512-xkfRPHbqSH4Ggx4eHRIO/eGL8XL4Ysb4woL8c87YuAo8Md7AUjyWKa9YMwTL519SyDPrfEgKdewjkxNCVeJW7w==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.5.tgz", + "integrity": "sha512-+XXdLN2CZLZcD/mO7mQtJMvCkzRfmODbeSKuMY/yXbGkzvA9rJyDY5qDYNoiz2kP/dmyAxXquL2BvLQLJFPQIg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.59.5", + "@typescript-eslint/visitor-keys": "5.59.5", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.5.tgz", + "integrity": "sha512-sCEHOiw+RbyTii9c3/qN74hYDPNORb8yWCoPLmB7BIflhplJ65u2PBpdRla12e3SSTJ2erRkPjz7ngLHhUegxA==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.59.5", + "@typescript-eslint/types": "5.59.5", + "@typescript-eslint/typescript-estree": "5.59.5", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.5.tgz", + "integrity": "sha512-qL+Oz+dbeBRTeyJTIy0eniD3uvqU7x+y1QceBismZ41hd4aBSRh8UAw4pZP0+XzLuPZmx4raNMq/I+59W2lXKA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.59.5", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/acorn": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "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": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/axios": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz", + "integrity": "sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==", + "dependencies": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/copy-anything": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-3.0.5.tgz", + "integrity": "sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==", + "dependencies": { + "is-what": "^4.1.8" + }, + "engines": { + "node": ">=12.13" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.40.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.40.0.tgz", + "integrity": "sha512-bvR+TsP9EHL3TqNtj9sCNJVAFK3fBN8Q7g5waghxyRsPLIMwL73XSKnZFK0hk/O2ANC+iAoq6PWMQ+IfBAJIiQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.4.0", + "@eslint/eslintrc": "^2.0.3", + "@eslint/js": "8.40.0", + "@humanwhocodes/config-array": "^0.11.8", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.0", + "eslint-visitor-keys": "^3.4.1", + "espree": "^9.5.2", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-sdsl": "^4.1.4", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-prettier": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz", + "integrity": "sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", + "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==", + "dev": true, + "dependencies": { + "prettier-linter-helpers": "^1.0.0" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "eslint": ">=7.28.0", + "prettier": ">=2.0.0" + }, + "peerDependenciesMeta": { + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", + "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", + "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/espree": { + "version": "9.5.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz", + "integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==", + "dev": true, + "dependencies": { + "acorn": "^8.8.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.2.12", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", + "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "dev": true + }, + "node_modules/follow-redirects": { + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", + "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "dev": true + }, + "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/ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-what": { + "version": "4.1.16", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.16.tgz", + "integrity": "sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==", + "engines": { + "node": ">=12.13" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/js-sdsl": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.4.0.tgz", + "integrity": "sha512-FfVSdx6pJ41Oa+CF7RDaFmTnCaFhua+SNYQX74riGOpl96x+2jQCqEfQ2bnXu/5DPCqlRuiqyvTJM0Qjz26IVg==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/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/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/peopledatalabs": { + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/peopledatalabs/-/peopledatalabs-6.1.5.tgz", + "integrity": "sha512-yIXxamojsUcC14hoTvGSrJGD/upgOAJ0sinjznzKAP0ftQEXTz9XDkq/QpKDFLnMVz0asWTHm3CcIVe8P3r0gQ==", + "dependencies": { + "axios": "^1.6.2", + "copy-anything": "^3.0.5" + } + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "node_modules/punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/semver": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "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": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", + "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=12.20" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + }, + "dependencies": { + "@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^3.3.0" + } + }, + "@eslint-community/regexpp": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", + "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==", + "dev": true + }, + "@eslint/eslintrc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz", + "integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.5.2", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + } + }, + "@eslint/js": { + "version": "8.40.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.40.0.tgz", + "integrity": "sha512-ElyB54bJIhXQYVKjDSvCkPO1iU1tSAeVQJbllWJq1XQSmmA4dgFk8CbiBGpiOPxleE48vDogxCtmMYku4HSVLA==", + "dev": true + }, + "@humanwhocodes/config-array": { + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", + "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", + "dev": true, + "requires": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + } + }, + "@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true + }, + "@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, + "@types/json-schema": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", + "dev": true + }, + "@types/node": { + "version": "18.16.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.9.tgz", + "integrity": "sha512-IeB32oIV4oGArLrd7znD2rkHQ6EDCM+2Sr76dJnrHwv9OHBTTM6nuDLK9bmikXzPa0ZlWMWtRGo/Uw4mrzQedA==", + "dev": true + }, + "@types/semver": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", + "dev": true + }, + "@typescript-eslint/eslint-plugin": { + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.5.tgz", + "integrity": "sha512-feA9xbVRWJZor+AnLNAr7A8JRWeZqHUf4T9tlP+TN04b05pFVhO5eN7/O93Y/1OUlLMHKbnJisgDURs/qvtqdg==", + "dev": true, + "requires": { + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.59.5", + "@typescript-eslint/type-utils": "5.59.5", + "@typescript-eslint/utils": "5.59.5", + "debug": "^4.3.4", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/parser": { + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.5.tgz", + "integrity": "sha512-NJXQC4MRnF9N9yWqQE2/KLRSOLvrrlZb48NGVfBa+RuPMN6B7ZcK5jZOvhuygv4D64fRKnZI4L4p8+M+rfeQuw==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "5.59.5", + "@typescript-eslint/types": "5.59.5", + "@typescript-eslint/typescript-estree": "5.59.5", + "debug": "^4.3.4" + } + }, + "@typescript-eslint/scope-manager": { + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.5.tgz", + "integrity": "sha512-jVecWwnkX6ZgutF+DovbBJirZcAxgxC0EOHYt/niMROf8p4PwxxG32Qdhj/iIQQIuOflLjNkxoXyArkcIP7C3A==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.59.5", + "@typescript-eslint/visitor-keys": "5.59.5" + } + }, + "@typescript-eslint/type-utils": { + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.5.tgz", + "integrity": "sha512-4eyhS7oGym67/pSxA2mmNq7X164oqDYNnZCUayBwJZIRVvKpBCMBzFnFxjeoDeShjtO6RQBHBuwybuX3POnDqg==", + "dev": true, + "requires": { + "@typescript-eslint/typescript-estree": "5.59.5", + "@typescript-eslint/utils": "5.59.5", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/types": { + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.5.tgz", + "integrity": "sha512-xkfRPHbqSH4Ggx4eHRIO/eGL8XL4Ysb4woL8c87YuAo8Md7AUjyWKa9YMwTL519SyDPrfEgKdewjkxNCVeJW7w==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.5.tgz", + "integrity": "sha512-+XXdLN2CZLZcD/mO7mQtJMvCkzRfmODbeSKuMY/yXbGkzvA9rJyDY5qDYNoiz2kP/dmyAxXquL2BvLQLJFPQIg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.59.5", + "@typescript-eslint/visitor-keys": "5.59.5", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/utils": { + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.5.tgz", + "integrity": "sha512-sCEHOiw+RbyTii9c3/qN74hYDPNORb8yWCoPLmB7BIflhplJ65u2PBpdRla12e3SSTJ2erRkPjz7ngLHhUegxA==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.59.5", + "@typescript-eslint/types": "5.59.5", + "@typescript-eslint/typescript-estree": "5.59.5", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.5.tgz", + "integrity": "sha512-qL+Oz+dbeBRTeyJTIy0eniD3uvqU7x+y1QceBismZ41hd4aBSRh8UAw4pZP0+XzLuPZmx4raNMq/I+59W2lXKA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.59.5", + "eslint-visitor-keys": "^3.3.0" + } + }, + "acorn": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "dev": true + }, + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "requires": {} + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "axios": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz", + "integrity": "sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==", + "requires": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "copy-anything": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-3.0.5.tgz", + "integrity": "sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==", + "requires": { + "is-what": "^4.1.8" + } + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" + }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + } + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "eslint": { + "version": "8.40.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.40.0.tgz", + "integrity": "sha512-bvR+TsP9EHL3TqNtj9sCNJVAFK3fBN8Q7g5waghxyRsPLIMwL73XSKnZFK0hk/O2ANC+iAoq6PWMQ+IfBAJIiQ==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.4.0", + "@eslint/eslintrc": "^2.0.3", + "@eslint/js": "8.40.0", + "@humanwhocodes/config-array": "^0.11.8", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.0", + "eslint-visitor-keys": "^3.4.1", + "espree": "^9.5.2", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-sdsl": "^4.1.4", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0" + }, + "dependencies": { + "eslint-scope": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", + "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, + "eslint-config-prettier": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz", + "integrity": "sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==", + "dev": true, + "requires": {} + }, + "eslint-plugin-prettier": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", + "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==", + "dev": true, + "requires": { + "prettier-linter-helpers": "^1.0.0" + } + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "eslint-visitor-keys": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", + "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", + "dev": true + }, + "espree": { + "version": "9.5.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz", + "integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==", + "dev": true, + "requires": { + "acorn": "^8.8.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + } + }, + "esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "dev": true + }, + "fast-glob": { + "version": "3.2.12", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", + "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "dependencies": { + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + } + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "requires": { + "flat-cache": "^3.0.4" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "requires": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + } + }, + "flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "dev": true + }, + "follow-redirects": { + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", + "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==" + }, + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "requires": { + "is-glob": "^4.0.3" + } + }, + "globals": { + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + }, + "globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + } + }, + "grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "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 + }, + "ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "dev": true + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true + }, + "is-what": { + "version": "4.1.16", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.16.tgz", + "integrity": "sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "js-sdsl": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.4.0.tgz", + "integrity": "sha512-FfVSdx6pJ41Oa+CF7RDaFmTnCaFhua+SNYQX74riGOpl96x+2jQCqEfQ2bnXu/5DPCqlRuiqyvTJM0Qjz26IVg==", + "dev": true + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "requires": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + } + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "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 + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "requires": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + } + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, + "peopledatalabs": { + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/peopledatalabs/-/peopledatalabs-6.1.5.tgz", + "integrity": "sha512-yIXxamojsUcC14hoTvGSrJGD/upgOAJ0sinjznzKAP0ftQEXTz9XDkq/QpKDFLnMVz0asWTHm3CcIVe8P3r0gQ==", + "requires": { + "axios": "^1.6.2", + "copy-anything": "^3.0.5" + } + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, + "prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "dev": true + }, + "prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "requires": { + "fast-diff": "^1.1.2" + } + }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "dev": true + }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" + } + }, + "semver": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "strip-ansi": { + "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": "^5.0.1" + } + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + }, + "typescript": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", + "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", + "dev": true + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true + } + } +} diff --git a/services/libs/types/package.json b/services/libs/types/package.json index 181f94c750..afb60c5efe 100644 --- a/services/libs/types/package.json +++ b/services/libs/types/package.json @@ -18,5 +18,8 @@ "eslint-plugin-prettier": "^4.2.1", "prettier": "^2.8.8", "typescript": "^5.0.4" + }, + "dependencies": { + "peopledatalabs": "~6.1.5" } } diff --git a/services/libs/types/src/enums/dashboard.ts b/services/libs/types/src/enums/dashboard.ts new file mode 100644 index 0000000000..2ed0d8a23d --- /dev/null +++ b/services/libs/types/src/enums/dashboard.ts @@ -0,0 +1,5 @@ +export enum DashboardTimeframe { + LAST_7_DAYS = '7d', + LAST_14_DAYS = '14d', + LAST_30_DAYS = '30d', +} diff --git a/services/libs/types/src/enums/featureFlags.ts b/services/libs/types/src/enums/featureFlags.ts index 03f8dddfc8..0080ff5d2e 100644 --- a/services/libs/types/src/enums/featureFlags.ts +++ b/services/libs/types/src/enums/featureFlags.ts @@ -7,10 +7,17 @@ export enum FeatureFlag { MEMBER_ENRICHMENT = 'member-enrichment', ORGANIZATION_ENRICHMENT = 'organization-enrichment', SEGMENTS = 'segments', + PRIORITIZED_QUEUES = 'prioritized-queues', FIND_GITHUB = 'find-github', // opensearch SYNCHRONOUS_OPENSEARCH_UPDATES = 'synchronous-opensearch-updates', + + // temporal + TEMPORAL_MEMBERS_ENRICHMENT = 'temporal-members-enrichment', + TEMPORAL_MEMBER_MERGE_SUGGESTIONS = 'temporal-member-merge-suggestions', + TEMPORAL_ORGANIZATION_ENRICHMENT = 'temporal-organization-enrichment', + SERVE_PROFILES_OPENSEARCH = 'serve-profiles-opensearch', } export enum FeatureFlagRedisKey { diff --git a/services/libs/types/src/enums/index.ts b/services/libs/types/src/enums/index.ts index 198fe35ec1..b2a67f964b 100644 --- a/services/libs/types/src/enums/index.ts +++ b/services/libs/types/src/enums/index.ts @@ -8,6 +8,8 @@ export * from './members' export * from './opensearch' export * from './organizations' export * from './platforms' +export * from './priorities' export * from './temporal' export * from './tenants' export * from './webhooks' +export * from './dashboard' diff --git a/services/libs/types/src/enums/members.ts b/services/libs/types/src/enums/members.ts index 9c60a95b2d..2462a52248 100644 --- a/services/libs/types/src/enums/members.ts +++ b/services/libs/types/src/enums/members.ts @@ -25,6 +25,7 @@ export enum MemberAttributeName { IS_TEAM_MEMBER = 'isTeamMember', IS_ORGANIZATION = 'isOrganization', IS_BOT = 'isBot', + IS_DELETED = 'isDeleted', TIMEZONE = 'timezone', KARMA = 'karma', SYNC_REMOTE = 'syncRemote', @@ -91,6 +92,10 @@ export const MemberAttributes = { name: MemberAttributeName.IS_BOT, label: 'is Bot', }, + [MemberAttributeName.IS_DELETED]: { + name: MemberAttributeName.IS_DELETED, + label: 'is Deleted', + }, [MemberAttributeName.KARMA]: { name: MemberAttributeName.KARMA, label: 'Karma', diff --git a/services/libs/types/src/enums/priorities.ts b/services/libs/types/src/enums/priorities.ts new file mode 100644 index 0000000000..94b89597c0 --- /dev/null +++ b/services/libs/types/src/enums/priorities.ts @@ -0,0 +1,14 @@ +import { TenantPlans } from './tenants' + +export enum QueuePriorityLevel { + SYSTEM = 'system', + NORMAL = 'normal', + HIGH = 'high', + URGENT = 'urgent', +} + +export interface IQueuePriorityCalculationContext { + onboarding?: boolean + dbPriority?: QueuePriorityLevel | null + plan: TenantPlans +} diff --git a/services/libs/types/src/enums/temporal.ts b/services/libs/types/src/enums/temporal.ts index 3dda198445..529d0af6d1 100644 --- a/services/libs/types/src/enums/temporal.ts +++ b/services/libs/types/src/enums/temporal.ts @@ -4,4 +4,6 @@ export enum TemporalWorkflowId { EMAIL_WEEKLY_ANALYTICS = 'email-weekly-analytics', EMAIL_EAGLEEYE_DIGEST = 'email-eagleeye-digest', + + MEMBER_UPDATE = 'member-update', } diff --git a/services/libs/types/src/enums/tenants.ts b/services/libs/types/src/enums/tenants.ts index fefd01911d..9758d95821 100644 --- a/services/libs/types/src/enums/tenants.ts +++ b/services/libs/types/src/enums/tenants.ts @@ -1,7 +1,34 @@ +import { FeatureFlag } from './featureFlags' + export enum TenantPlans { Essential = 'Essential', Growth = 'Growth', EagleEye = 'Eagle Eye', Scale = 'Scale', - Enterprise = 'enterprise', + Enterprise = 'Enterprise', +} + +export const PLAN_LIMITS = { + [TenantPlans.Essential]: { + [FeatureFlag.AUTOMATIONS]: 2, + [FeatureFlag.CSV_EXPORT]: 2, + }, + [TenantPlans.Growth]: { + [FeatureFlag.AUTOMATIONS]: 10, + [FeatureFlag.CSV_EXPORT]: 10, + [FeatureFlag.MEMBER_ENRICHMENT]: 1000, + [FeatureFlag.ORGANIZATION_ENRICHMENT]: 200, + }, + [TenantPlans.Scale]: { + [FeatureFlag.AUTOMATIONS]: 20, + [FeatureFlag.CSV_EXPORT]: 20, + [FeatureFlag.MEMBER_ENRICHMENT]: Infinity, + [FeatureFlag.ORGANIZATION_ENRICHMENT]: Infinity, + }, + [TenantPlans.Enterprise]: { + [FeatureFlag.AUTOMATIONS]: Infinity, + [FeatureFlag.CSV_EXPORT]: Infinity, + [FeatureFlag.MEMBER_ENRICHMENT]: Infinity, + [FeatureFlag.ORGANIZATION_ENRICHMENT]: Infinity, + }, } diff --git a/services/libs/types/src/members.ts b/services/libs/types/src/members.ts index 0d8e684577..8043c916d3 100644 --- a/services/libs/types/src/members.ts +++ b/services/libs/types/src/members.ts @@ -39,11 +39,12 @@ export interface IMember { displayName?: string avatarUrl?: string score: number - lastEnriched: string + lastEnriched?: Date | null + enrichedBy?: string[] | null joinedAt: string createdAt: string manuallyCreated: boolean - reach: number + reach?: number numberOfOpenSourceContributions: number activeOn: string[] activityCount: number @@ -55,8 +56,22 @@ export interface IMember { toMergeIds: string[] noMergeIds: string[] // eslint-disable-next-line @typescript-eslint/no-explicit-any - username: any + username: PlatformIdentities lastActivity: unknown + bio?: string + location?: string + // eslint-disable-next-line @typescript-eslint/no-explicit-any + contributions?: any +} + +export type PlatformIdentities = { + [K in keyof typeof PlatformType]?: [MemberIdentity] +} + +export interface MemberIdentity { + username: string + integrationId: string + sourceId?: string } export interface IMemberSyncRemoteData { @@ -68,3 +83,9 @@ export interface IMemberSyncRemoteData { metaData: string lastSyncedAt?: string } + +export interface IMemberMergeSuggestion { + similarity: number + activityEstimate: number + members: [string, string] +} diff --git a/services/libs/types/src/opensearch.ts b/services/libs/types/src/opensearch.ts index ba245e2bce..0594d89ce6 100644 --- a/services/libs/types/src/opensearch.ts +++ b/services/libs/types/src/opensearch.ts @@ -13,7 +13,7 @@ export interface MemberStaticFieldsTranslation { score: string lastEnriched: string joinedAt: string - totalReach: string + reach: unknown numberOfOpenSourceContributions: string activeOn: string activityCount: string diff --git a/backend/src/services/premium/enrichment/types/memberEnrichmentTypes.ts b/services/libs/types/src/premium/enrichment/member.ts similarity index 93% rename from backend/src/services/premium/enrichment/types/memberEnrichmentTypes.ts rename to services/libs/types/src/premium/enrichment/member.ts index 6276a46ccf..adced43f3a 100644 --- a/backend/src/services/premium/enrichment/types/memberEnrichmentTypes.ts +++ b/services/libs/types/src/premium/enrichment/member.ts @@ -81,11 +81,13 @@ export interface EnrichmentAPIMember { export interface EnrichmentAPIResponse { profile: EnrichmentAPIMember + // eslint-disable-next-line @typescript-eslint/no-explicit-any error?: any } export interface EnrichmentCache { memberId: string + // eslint-disable-next-line @typescript-eslint/no-explicit-any data: any createdAt: string updatedAt: string diff --git a/services/libs/types/src/premium/index.ts b/services/libs/types/src/premium/index.ts new file mode 100644 index 0000000000..7fd5f001de --- /dev/null +++ b/services/libs/types/src/premium/index.ts @@ -0,0 +1 @@ +export * from './enrichment/member' diff --git a/services/libs/types/src/queue/index.ts b/services/libs/types/src/queue/index.ts index c0cf792c22..d298327fe7 100644 --- a/services/libs/types/src/queue/index.ts +++ b/services/libs/types/src/queue/index.ts @@ -4,11 +4,22 @@ export interface IQueueMessage { export interface ISqsQueueReceiver { start(): Promise - stop() + + stop(): void + processMessage(data: IQueueMessage): Promise } export interface ISqsQueueEmitter { init(): Promise - sendMessage(groupId: string, message: IQueueMessage, deduplicationId?: string): Promise + + sendMessage( + groupId: string, + message: T, + deduplicationId?: string, + ): Promise + + sendMessages( + messages: { payload: T; groupId: string; deduplicationId?: string; id?: string }[], + ): Promise } diff --git a/services/libs/types/src/queue/integration_sync_worker/index.ts b/services/libs/types/src/queue/integration_sync_worker/index.ts index 27900f991d..42d7b4791e 100644 --- a/services/libs/types/src/queue/integration_sync_worker/index.ts +++ b/services/libs/types/src/queue/integration_sync_worker/index.ts @@ -1,3 +1,5 @@ +import { AutomationSyncTrigger } from '../../automations' + export enum IntegrationSyncWorkerQueueMessageType { SYNC_ALL_MARKED_MEMBERS = 'sync_all_marked_members', SYNC_MEMBER = 'sync_member', @@ -5,3 +7,30 @@ export enum IntegrationSyncWorkerQueueMessageType { SYNC_ORGANIZATION = 'sync_organization', ONBOARD_AUTOMATION = 'onboard_automation', } + +export interface IIntegrationSyncWorkerEmitter { + triggerSyncMarkedMembers(tenantId: string, integrationId: string): Promise + + triggerSyncMember( + tenantId: string, + integrationId: string, + memberId: string, + syncRemoteId: string, + ): Promise + + triggerOnboardAutomation( + tenantId: string, + integrationId: string, + automationId: string, + automationTrigger: AutomationSyncTrigger, + ): Promise + + triggerSyncMarkedOrganizations(tenantId: string, integrationId: string): Promise + + triggerSyncOrganization( + tenantId: string, + integrationId: string, + organizationId: string, + syncRemoteId: string, + ): Promise +} diff --git a/services/libs/types/src/queue/nodejs_worker/index.ts b/services/libs/types/src/queue/nodejs_worker/index.ts index bb83e1276a..8577f246a5 100644 --- a/services/libs/types/src/queue/nodejs_worker/index.ts +++ b/services/libs/types/src/queue/nodejs_worker/index.ts @@ -1,12 +1,19 @@ +import { AutomationTrigger, AutomationType } from '../../automations' import { IQueueMessage } from '../' +/* eslint-disable @typescript-eslint/no-explicit-any */ + export enum NodejsWorkerQueueMessageType { NODE_MICROSERVICE = 'node_microservice', } +export enum ExportableEntity { + MEMBERS = 'members', +} + export class NewActivityAutomationQueueMessage implements IQueueMessage { public readonly type: string = NodejsWorkerQueueMessageType.NODE_MICROSERVICE - public readonly trigger = 'new_activity' + public readonly trigger = AutomationTrigger.NEW_ACTIVITY public readonly service = 'automation' constructor( @@ -18,8 +25,105 @@ export class NewActivityAutomationQueueMessage implements IQueueMessage { export class NewMemberAutomationQueueMessage implements IQueueMessage { public readonly type: string = NodejsWorkerQueueMessageType.NODE_MICROSERVICE - public readonly trigger = 'new_member' + public readonly trigger = AutomationTrigger.NEW_MEMBER public readonly service = 'automation' - constructor(public readonly tenant: string, public readonly memberId: string) {} + constructor( + public readonly tenant: string, + public readonly memberId: string, + public readonly segmentId: string, + ) {} +} + +export class ProcessAutomationQueueMessage implements IQueueMessage { + public readonly type: string = NodejsWorkerQueueMessageType.NODE_MICROSERVICE + public readonly service = 'automation-process' + + constructor( + public readonly tenant: string, + public readonly automationType: AutomationType, + public readonly automation: any, + public readonly eventId: string, + public readonly payload: any, + ) {} +} + +export class BulkEnrichQueueMessage implements IQueueMessage { + public readonly type: string = NodejsWorkerQueueMessageType.NODE_MICROSERVICE + public readonly service = 'bulk-enrich' + + constructor( + public readonly tenant: string, + public readonly memberIds: string[], + public readonly segmentIds: string[], + public readonly notifyFrontend: boolean, + public readonly skipCredits: boolean, + ) {} +} + +export class ExportCSVQueueMessage implements IQueueMessage { + public readonly type: string = NodejsWorkerQueueMessageType.NODE_MICROSERVICE + public readonly service = 'csv-export' + + constructor( + public readonly user: string, + public readonly tenant: string, + public readonly entity: ExportableEntity, + public readonly segmentIds: string[], + public readonly criteria: any, + ) {} +} + +export class EagleEyeEmailDigestQueueMessage implements IQueueMessage { + public readonly type: string = NodejsWorkerQueueMessageType.NODE_MICROSERVICE + public readonly service = 'eagle-eye-email-digest' + + constructor(public readonly tenant: string, public readonly user: string) {} +} + +export class IntegrationDataCheckerQueueMessage implements IQueueMessage { + public readonly type: string = NodejsWorkerQueueMessageType.NODE_MICROSERVICE + public readonly service = 'integration-data-checker' + + constructor(public readonly tenantId: string, public readonly integrationId: string) {} +} + +export class WeeklyAnalyticsEmailQueueMessage implements IQueueMessage { + public readonly type: string = NodejsWorkerQueueMessageType.NODE_MICROSERVICE + public readonly service = 'weekly-analytics-emails' + + constructor(public readonly tenant: string) {} +} + +export class StripeWebhookQueueMessage implements IQueueMessage { + public readonly type: string = NodejsWorkerQueueMessageType.NODE_MICROSERVICE + public readonly service = 'stripe-webhooks' + + constructor(public readonly event: any) {} +} + +export class SendgridWebhookQueueMessage implements IQueueMessage { + public readonly type: string = NodejsWorkerQueueMessageType.NODE_MICROSERVICE + public readonly service = 'sendgrid-webhooks' + + constructor(public readonly event: any) {} +} + +export class RefreshSampleDataQueueMessage implements IQueueMessage { + public readonly type: string = NodejsWorkerQueueMessageType.NODE_MICROSERVICE + public readonly service = 'refresh-sample-data' +} + +export class EnrichOrganizationQueueMessage implements IQueueMessage { + public readonly type: string = NodejsWorkerQueueMessageType.NODE_MICROSERVICE + public readonly service = 'enrich-organizations' + + constructor(public readonly tenantId: string, public readonly maxEnrichLimit: number) {} +} + +export class MergeSuggestionsQueueMessage implements IQueueMessage { + public readonly type: string = NodejsWorkerQueueMessageType.NODE_MICROSERVICE + public readonly service = 'merge-suggestions' + + constructor(public readonly tenant: string) {} } diff --git a/services/libs/types/src/temporal/automations.ts b/services/libs/types/src/temporal/automations.ts index 1264ca4f30..903f13e812 100644 --- a/services/libs/types/src/temporal/automations.ts +++ b/services/libs/types/src/temporal/automations.ts @@ -17,3 +17,8 @@ export interface ITriggerMemberAutomationArgs { automationId: string memberId: string } + +export interface IProcessGenerateMemberMergeSuggestionsArgs { + tenantId: string + lastUuid?: string +} diff --git a/services/libs/types/src/temporal/cache.ts b/services/libs/types/src/temporal/cache.ts new file mode 100644 index 0000000000..8e5ed585ec --- /dev/null +++ b/services/libs/types/src/temporal/cache.ts @@ -0,0 +1,5 @@ +export interface IProcessRefreshDashboardCacheArgs { + tenantId: string + segmentId?: string + leafSegmentIds?: string[] +} diff --git a/services/libs/types/src/temporal/index.ts b/services/libs/types/src/temporal/index.ts index 26e659f79a..41ca6de385 100644 --- a/services/libs/types/src/temporal/index.ts +++ b/services/libs/types/src/temporal/index.ts @@ -1 +1,2 @@ export * from './automations' +export * from './cache' diff --git a/services/libs/types/tsconfig.json b/services/libs/types/tsconfig.json index 4d0dee19d0..6730edb9e7 100644 --- a/services/libs/types/tsconfig.json +++ b/services/libs/types/tsconfig.json @@ -10,6 +10,7 @@ "esModuleInterop": true, "baseUrl": "./src", "paths": { + "@crowd/*/premium": ["../../*/src/premium"], "@crowd/*": ["../../*/src"] } }, diff --git a/services/scripts/lint_apps.sh b/services/scripts/lint_apps.sh index dea8f23890..10df5bfe02 100755 --- a/services/scripts/lint_apps.sh +++ b/services/scripts/lint_apps.sh @@ -12,3 +12,11 @@ for app_dir in $CLI_HOME/../apps/*/; do (cd "$app_dir" && pnpm run lint && pnpm run format-check && pnpm run tsc-check && say "App $app: linter, prettier and typescript checked!" && nl) fi done + +for app_dir in $CLI_HOME/../apps/premium/*/; do + if [ -f "${app_dir}package.json" ]; then + app=$(basename $app_dir) + yell "Checking linting, prettier and typescript for app: $app!" + (cd "$app_dir" && pnpm run lint && pnpm run format-check && pnpm run tsc-check && say "App $app: linter, prettier and typescript checked!" && nl) + fi +done \ No newline at end of file